I'm making an app. Part of the app is to choose from 5 preset images.
These will be available at install and so need to be bundled with the app.
However, there is also potential to "add" more images through in app purchases.
I'm looking for the "best" way to store these images on the device with the potential to add/unlock more images.
My thoughts are that "CoreData" is too heavy for this. I could do some sort of plist thing to reference the initial five images. But then how do I add more through IAP?
With IAP, do I download the additional images upon purchase? Or should they also be bundled into the app at install and then unlocked when purchased?
Never done IAP stuff before and my previous apps all used Core-Data as they were very data heavy.
There are two things to consider -
Do you want to add more images after you've shipped?
Are the images small enough that they can be download quickly on demand?
If the answer to either is yes, I would recommend going the hosted content route. Apple even allows you to host content on their servers.
Otherwise, just bundle everything in your app and unlock as required.
Small note on security: I would not worry about piracy at all since there is no way you can stop people from pirating content/apps. Besides, the number of people who JB is quite small (23m / 90% * 500m ~ 5%) and the number of people who pirate is even smaller.
Related
here is a question from a total beginner in mobile app development :)
I am building a React Native application for iOS platform first. I am stuck with decision on how to deliver icons to the application. Imagine:
I have a reference data set with eg travelling options (bike, motorbike, etc).
The actual set is much bigger though - I am expecting rather 100-200 items with one icon each for the UI.
These should be cached in the application.
Most of them wont change, new ones might come to the set periodically, but not even every week.
Now to the options I was thinking of:
Deliver a sqlite database with images as BLOB and update the database when new icons arrive
Deliver a sqlite database with image URLs for S3 bucket items and update the database when new icons arrive
Deliver the app with initial sqlite bundled with BLOB or URLs(?) and update over the air when new icons arrive
Do not use sqlite database at all and deliver all with REST API call on startup with image URLs. Load images when needed and cache them. Update database with new icon URLs when new icons arrive.
I think I tend to be using Option 4 because it seems least heavy on the client - he can always download the icon whenever he needs one. But it also has a latency because of downloading the icon for the first time from private s3 bucket.
However I am missing real-world experience in mobile apps and probably missing important details. Hoping for some insight from experts. Thanks for any pro and con you can deliver on this options!
You are right, no database needed at all.
So basically you have to load those icons only once and cache them inside the app. You can you something like react-native-fast-image or do caching by yourself.
If URL of icon was changed - the new image will be cached.
So on real-world apps, you usually have the image placeholders (example below) or loaders (more rare).
If you have multiple types of vehicle, you can create multiple placeholders and show them unless the original image is loading/not available.
Using react native firebase storage and firestore is a good option. The images can be loaded remotely and the caching is done automatically
I'm working on an iOS app, but if there is an answer here, it may apply to other platforms as well.
There are basically two ways to validate an in-app purchase: locally and server-side. The server side method is documented here. (I can't find the docs for the local method at the moment.)
Let's say I validate the purchase server-side. My question is about what happens after that, to enable the purchased feature(s). I don't see documentation on this. Am I missing it?
I imagine two or three steps:
Server sends an HTTPS response to the iOS app, saying "yes, you made X purchase".
The app flips some boolean variable in memory to enable the purchased features.
[Maybe] The app saves this state to local storage so that it doesn't need to revalidate the receipt via the internet every time it launches.
All of these steps seem vulnerable to attack on a hacked/jailbroken client device. Obviously there are tradeoffs between the difficulty of hacking and the cost of the in-app purchase and potential lost revenue. I'm thinking about the case where the app is more expensive or popular and there may be incentive to hack it.
Example possible vulnerabilities: (again, all of these probably require a helpful - to the hacker - OS kernel)
a real server response could be sniffed and inspected and then faked for other users
the app's memory could be inspected and the boolean variable flipped
if the state is saved (for example, in a file, or in the user defaults key-value store) that state could be altered
So, are there some techniques to mitigate or prevent these hacks? Or do companies simply accept that a determined hacker can steal software, and take it as part of the cost of doing business?
Don't know if there is a "correct" answer here since you outlined it pretty well:
Obviously there are tradeoffs between the difficulty of hacking and the cost of the in-app purchase and potential lost revenue.
If there was an official way of handling this then it does just become a target for hacking.
Most apps I've seen (even large ones) are keeping data in local storage to determine purchase status. But... you can keep this data on a short cache and refresh it in the background every 5 min or so. That way a hacker would need to overwrite it every 5min which makes normal usage pretty impractical.
Unless you have a high cost of supporting users (e.g. Spotify paying licensing costs) then there's probably better areas to invest in than this.
I am making a game in Swift with SpriteKit that I envision to have (for now) about 100 levels. They're broken out into areas (20 levels per area). Most areas are free, but I'd like to make one or two very special areas that require some hard work to get the ability to play. Maybe i'll even make one require a purchase if it's worth it.
So to make things easy, I just made all the levels as JSON configuration files when needed, and my reader will pull the settings and hydrate the level class from that. Thus I have 100 level files.
I was thinking about this, and realized that there isn't anything stopping an attacker from using a tool like ifunbox to browse to the JSON files, find the premium ones, take the contents, overwrite the non-premium ones, and then play the premium content for free.
Should I keep the JSON files and just encrypt them? I was thinking another alternative would be to keep level hashes of each level and do a comparison, but that would require 100 hashes in my code file.
Could someone offer me a suggestion as to protect my level configuration data a little better so premium content stays premium?
Thanks!
Maybe you should use apples On Demand Resources so that the files arent actually in the app to begin with, and it will only download the premium maps once the purchase has been made
Benefits of On-Demand Resources
Some of the main ways apps can benefit from on-demand resources
include:
Smaller app size. The size of the app bundle downloaded by the user is
smaller resulting in faster downloads and more storage room on the
device.
Lazy loading of app resources. The app has resources that are
used only in certain states. The resources are requested when the app
is likely to enter the appropriate state. For example, in a game with
many levels, the user needs only the resources associated with the
current and next levels.
Remote storage of rarely used resources. The
app has resources that are used infrequently. The resources are
requested as they are needed. For example, an app tutorial is usually
shown once after the app is opened for the first time, and may never
be used again. The app requests the tutorial on first launch, and then
requests the tutorial only when needed or when new features are added.
Remote storage of in-app purchase resources. The app offers in-app
purchases that includes additional resources. The resources for
purchased modules are requested by the app after it is launched. For
example, a user purchases the SuperGeeky emoticon pack in a keyboard
app. The app requests the pack after it finishes launching.
We're using Parse in our iOS app and we've discovered that our app is using an enormous amount of space -around 2.3GB in some devices- in storage. After downloading app data to my Mac, I've realized almost all of that data is the cached images in a folder called PFFileStaging, it contains highest resolution PNGs of all the PFFiles that the user has viewed in our app, ever. How can we disable this behavior, at least limit it? Is that the intended behavior? I heavily doubt using GBs of space is the intended behavior. Is this a bug?
Unfortunately this is not cache related (as per Parse's engineers: "this is used to ensure that no concurrent modification happens to the file after you request uploading").
They're planning to implement automatic trimming of PFFileStaging folder on every app start (as per road plan this should appear in next version 1.8.2).
See the the whole thread on GitHub.
We have a Universal iOS app. We use JSON to download content into the app during the first launch.
The size of content being downloaded on iPad (due to large image sizes) is about 100MB and on iPhone (smaller images) 80MB.
It takes about 4-7 minutes to download all content over WiFi. On 3G it takes 7-10 minutes.
Images are large in size, text content is not so much.
Is there any way we could reduce the download time? I'm aware of JSON compression but not sure if it will help with images?
Any ideas?
Tx
Some of this information has been mentioned in various comments, but it's what I would have suggested anyway and I figured having an answer written up would be more useful, so here goes:
Instead of storing the location of each image in the JSON file and downloading them one at a time, store the images in zip files and download those. Any amount of compression you get from this is an improvement in your download time, and you can simply unzip the images once you've downloaded the zip files.
Store a reasonable amount of the images in the main bundle along with the app. In your case you clearly can't store them all there; you don't want to have a huge app, and since it's a recipe app I presume you'll be adding more recipes as you go along. It makes a lot more sense to be able to update and download recipes via the JSON than to have to push a new version of the app to the app store with each change. But there are some items that can be bundled with the app; ex. large background images, design elements that are constant and unlikely to change. Any image which won't be likely to need updating should be bundled with the main app; any savings on download time is an improvement.
Have some kind of interesting loading screen. This is very important since you're talking about 4-10 minute download times. That is a long time for a user. When engaging with an application, 30 seconds can even seem like a long time. You're going to be hard pressed to make me willing to sit there and wait for 10 minutes for the app to begin if nothing is happening during that time. Have creative vegetable characters move across the screen, include a little interactive puzzle or ingredients on the loading screen, something. Just give the user something to look at (or preferably something interactive to do) while they're waiting. Otherwise you're probably going to lose a lot of users during this download.
If you can make this work, it really is a good idea to only download items when necessary. For example if your recipe app is broken into "Salads", "Fish", "Chicken", "Desserts", etc., you could prompt the user to download the recipe information for each category the first time they click on it. The great thing about this is that it breaks up the time the user has to spend waiting on the download; let's say you have 10 recipe categories, now the time the user has to wait all at once has been decreased from 4-10 minutes to 30 seconds-1 minute. That is a huge difference. I'll wait 1 minute for the Dessert recipes (still give them something to do!) much more readily than I'll wait 10 minutes for the whole app.
4b. You mentioned not being able to access new content while offline, which is a valid concern. To address this you could have a prompt the first time the app loads: This application contains hundreds of exciting recipes and delicious images. It can take several minutes to download all this yummy information. You can download all the content now, or proceed to the app and download recipes by category when you wish to view them. Please note that this will require an internet connection. And the buttons could say something like Download Now and Proceed to App. Obviously you can play with the wording to your heart's content, but the idea is sound. You've informed the user that there might be a significant download time, so at least they're forewarned, and they can make their own decision about how to use your app.
However you decide to proceed, break up the content you download into logical categories for the zip files. For example, "Desserts.zip", "Salads.zip", etc. That way even if you don't decide to let the user download on-demand now, you've set up a structure that is open to change later on.