I am writing an app that requires the ability to pull data from a cloud database and store the data locally. I'm using SQLite to store the data when i collect it from the cloud DB, but it's knowing what to do with images.
In the cloud database, I have a URL string pointing to the image. So i now need to be able to grab that image and store it somewhere locally so that i can reference in my code (i need to be able to access it with no internet, so needs to be cached or saved somewhere).
I've done a lot of reading on this but there seems to be some contradiction and dispute in terms of the best way to efficiently store images locally and where. I assume i need to store it as a Bitmap image, but where is considered best for this?
Ideally if the app is deleted, the images should also be deleted. I'm targeting Andorid 4.3 and above only if that makes any difference.
Any pointers appreciated. Thanks.
Store them in the applicatoin package path under the files directory: /data/data/com.your.package.name/files. This directory is removed when your app is uninstalled from the device.
You can access this directory by using:
string filesPath = System.Environment.GetFolderPath (System.Environment.SpecialFolder.Personal);
Related
Is there a place where I can store and manage my own images outside of internal storage? I don't want other apps to be able to see or access these images. Should I use external storage? Does such a place exist in the new MediaStore? It's fine if they're deleted when the app is deleted.
This solution needs to support API 21 or higher.
I know there are a lot of questions like this, but they're 10+ years old and a lot has changed since then.
Use case / background
I have an app where all data is stored locally on the device (no external servers).
Users can choose custom background images for journal entries. A user could choose to use a different image for each journal entry they create. They can create as many journal entries as they want. They may revisit those journal entries. So, I need to store an unknown amount of images for the lifetime of the app. I've been saving a copy of the images the user picks from the gallery in my local app storage via context.filesDir.
I noticed a crash Fatal Exception: android.database.sqlite.SQLiteDiskIOException disk I/O error (code 4874 SQLITE_IOERR_SHMSIZE) and after googling, I found This error may indicate that the underlying filesystem volume is out of space.
My concern is that my app is running out of internal storage space because of the user images I'm storing.
Where should I be storing these images? I originally chose internal storage because I wanted my users' images to be reasonably private (since I don't know if they're storing sensitive images or not). I also wanted to make sure the images would always be available even if the source image (chosen from user's media) is deleted. However, I hadn't considered the limits imposed on internal storage. Silly me!
Darshil's answer is correct. Using the recommended Storage Access Framework for your use case, you should use getFilesDir() which will return your app's internal storage, which is private to your app.
Where should I be storing these images?
problem is due to limit of resource which is out of our control. However if you really want to store all the images, you can take some approaches:
1. Online: Use some cloud servers for storing user data. This might cost you a lot.
2. Offline: Tell user that you have only the limited amount of storage and storing more images will require to delete some older ones.
3. Both: Store in device. When internal storage is running low, tell user to buy some type of premium subscription to store unlimited cloud photos.
Android does not provide a place for you to store private photos (can't be accessed by user or other apps) outside of app's internal storage. I know you can contradict me by saying that one can store them in external storage by using getExternalStoragePublicDirectory() but the problem is that it is a shared directory accessible to users and other apps and remains when the app is deleted.
So I suggest you to use getFilesDir() as the directory returned by it is hidden from users and is deleted when the app is deleted. And also implement a image compressing tool in your app which automatically compresses images when uploaded by the user and then save it to internal storage. This won't solve the problem completely but I guess it's a start.
I would recommend checking out AWS Amplify which allows you to integrate your application with AWS services. For what you have described, you could use amplify to give your app the ability to authenticate users and set up cloud storage on AWS S3 which you can configure to only allow users to access and edit files that they have uploaded. One nice thing about AWS Amplify and AWS S3 cloud storage is that there is a free tier which allows you to develop your application for little to no cost. Depending on the amount of data that you will be uploading, it may be quite a while before you surpass the free tier limits.
A guide like this one may help you learn more.
I am not sure if I fully understand your question, but writing a quick tip.
try cloud services to store your images like AWS s3, cloudinary. Cloudinary is much cheaper if you want to try like 25gb/month free.
With limited storage space appearing to be the root cause, I recommend intentionally using the UI to encourage users to use existing images over new images. (This can work in addition to the technical options provided in other answers)
For example, present the user with a list of available background images and a link to add a new image. In this case, using an existing image is 1 click with a preview, where getting a new image requires opening a new view and searching for the new image.
Using the UI in this way doesn't directly get you more space, but it can help you to more efficiently use the space you have by guiding users to use existing images. It also gives you a place to warn about (or limit) adding more images when there is not more space available.
*If you still must have more storage on the device outside of the app, you could try using the public space with encryption for "privacy".
My flutter app provides some content (mostly text and graphics, like blog posts, or news) to its users. These contents need to be updated daily. So there will be new texts, images, maybe even videos. Now, the app would be used even when offline, so all the updated contents should be stored somewhere to be accessed later.
Right now, I'm using a SQLite DB to store texts
The images are stored in the Assets folder of the app.
The nature of the program is such that the users won't want to give the app any SD-Card access permission.
So my question is, how can I update the content without updating the whole app or using any SDcard permissions?
Is it possible to write code that downloads the new content and saves them directly in the Assets folder of the app? Can the app then use the files? without them being referenced in "pubspec.YAML" file?
Can I store all the data (even images and videos which are added daily) in my SQLite DB which is located in phone memory?
What is the standard practice for apps that have this kind of content?
You have to use the storage somehow.
In Android, you don't have to ask for storage permission if you want to save data in internal directory for your app which is storage/emulated/0/Android/data/data/your_package_name/ folder. You can try that.
However it has got a downside, if your app is deleted then all the data will also be deleted.
I'm writing an android app that makes use of many images(dozens). These images, like most of the other data in the app, are updated from a remote database. For the data I am going to have a local database and sync it with the remote database every time the remote db is updated.
The remote database will store the images as URLs, and my app will download the images from these urls to display them in the app. So I could just have my local database sync with the remote one and I'll have the URL of all the image files I'm using and I can re download them from the remote server every time the app is run, but this is obviously slow and wastes a lot of data.
What I want to do is, everytime the database is updated and needs to be synced, the app will sync its local db and download the new images from their URLs as usual, but then it will save the image files somewhere on the device, so next time the app is run it can just grab the images from the device.
I can't seem to find an effective way of doing this, perhaps it's because it's a bad idea to do it this way in the first place? Sharepreferences probably won't have enough room, external storage isn't available all the time, and I hear it's a bad idea to just store a big chunk of binary data(such as an image) in the local database.
What are my options here?
Start with Android Storage Options.
Further:
external storage isn't available all the time
That's true in theory, but in practice, you'll have external storage 99% of the time, especially if you're developing for newer devices. Note that "external storage" and SD Card aren't the same thing -- the terminology here is confusing. For this, use getExternalFilesDir().
Regardless, if your image storage is a reasonable amount (<100MB is reasonable IMHO), then you can just use internal storage. As of Android 3.x, this won't cause a device to run out of space like early devices did. In practice, you'll be fine 99% of the time. Here you might want to use the cache dir, returned by getCacheDir().
In one of my apps I have a large number of files that are synced with a CDN. I use the sync process and database to retrieve download URLs and MD5 hashes of the files. If the MD5 hash has changed, then I download the file again in the background. I simply store the file using the hash as the file-name, so I can easily resolve duplicate files. Periodically, I also walk the cacheDir to see whether there are any files that are no longer referenced in the database.
I'm looking at this page, which explains how to use a database in the local Android project (in Assets), to populate the application standard database (managed by Android, in data/...) like this. In this way all the data in the assets database are readable in the apk freely, right?
This is not a good way to store data if in the database there is personal info or certificates.
What is the best way store big info data in assets db and personal data in res/xml or res/values? Is there a recommended way to store personal data?
APK files in Android are world-readable by default, so storing sensitive data in there is not a good idea. On JellyBean and later, the app can be forward-locked (aka 'app encryption') which will ensure that your private assets cannot be read by other applications. This is done automatically for paid apps.
The best way would be to not store the data in the APK but download it on first install. You can use Google Play expansion files, which require authentication to download or come up with your own solution.
You could store them in some encrypted form and then decrypt them on first run, but then you will have key management issues.
As luck would have it I was reading about this today. The Android Dev guide suggests that you use internal storage for private data as it is inaccessible to other apps or the user. See http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
I hope that helps.
I have files that I want to save so they are not accessible by other applications and that are safe from updates (won't be deleted).
My Problem
I am not sure where to save them. I know that I can save them in the data directory using the below code to get the path but I'm not sure if this is correct.
Environment.getDataDirectory();
My Question
Is the applications data directory the correct place to store my data or is it meant just for system data?
If it isn't the correct place, could you suggest where is?
Thanks in advance
I'm sure you have already come across this
http://developer.android.com/guide/topics/data/data-storage.html
In that you see Internal storage is usually a methodology which helps in achieving what you asked for. Yes you can use the function which you have shown
or
(OWNERACTIVITY).getFilesDir().getAbsolutePath()
should give you the location where data for the application gets stored.
If you are keeping files in SD card, all applications (with android.permission.READ_EXTERNAL_STORAGE) can access the data. The best place is is keep them in your data directory. Your application can access the data as long as your package name and certificate is not changed. If you want to store some files like images and audio, you can store them in SD card in a directory with .nomedia in it. But if you want to keep some data files, checksums etc, it is better to keep them in data directory. Even if you update your application, you should still be able to access it.
YOu can read more here