I am making a flutter app where i have to download files from the a distant server.
but I want to make those files only accessible from my app, and not from other file managers or other apps like Netflix does with their app.
how can I achieve that in flutter?
thank you in advance.
you can use flutter_cache_manager
A CacheManager to download and cache files in the cache directory of the app. Various settings on how long to keep a file can be changed.
It uses the cache-control http header to efficiently retrieve files.
example
var file = await DefaultCacheManager().getSingleFile(url);
How it works
By default the cached files are stored in the temporary directory of the app. This means the OS can delete the files any time.
Information about the files is stored in a database using sqflite. The file name of the database is the key of the cacheManager, that's why that has to be unique.
This cache information contains the end date till when the file is valid and the eTag to use with the http cache-control.
Related
I already have a SQLite database (.db) file available for download at a specific URL (let's say https://mywebsite.com/mydb.db). I want to download this file and use it inside my Kotlin Android app. I can download the file to the "Downloads" folder in my device emulator, but I have several questions about where to go from here.
Do I need to copy this file to internal storage, or can I create a database directly from the file in the Downloads folder? I want the database data to persist locally, so I don't want to leave the database file in a place where it may get deleted (the Downloads folder).
Basically, I'd like the app to be able to read from a persistent, internal .db file
Sometimes, I'll need to add more data to the .db file. In the future, when I re-download the .db file and create a database from it, will this overwrite the existing database in the app's internal storage? Do I need to manually delete old iterations of the database?
I'd like to download the .db file automatically the first time the app runs, and every time I upload a new version of the .db file to https://mywebsite.com/mydb.db.
In general, I'm very new to Android development, so I'm not sure what the best practices are. The code I've provided successfully downloads my .db file to the "Downloads" folder on a button click. I'm not sure where to go from here in terms of creating a database from the .db file, and automatically replacing the database when I upload a new .db file to my host URL.
private const val PERMISSION_CODE = 1000
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
downloadButton.setOnClickListener {
// Checks if version of Android is >= Marshmallow
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_DENIED){
// request permission if denied
requestPermissions(arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), PERMISSION_CODE)
}
else {
startDownload()
}
}
else {
// OS is out of date, no permissions are needed
startDownload()
}
}
private fun startDownload() {
val request = DownloadManager.Request(Uri.parse(getString(R.string.db_URL)))
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
request.setTitle("my_database.db")
request.setDescription("My database is downloading.")
request.allowScanningByMediaScanner()
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "mydb_" + "${System.currentTimeMillis()}")
val manager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
manager.enqueue(request)
}
Do I need to copy this file to internal storage, or can I create a database directly from the file in the Downloads folder?
The file is the database and can therefore be opened from the downloads folder.
I want the database data to persist locally, so I don't want to leave the database file in a place where it may get deleted (the Downloads folder).
You could copy the file from the downloads folder and place it in the default location for the App based upon the Context's getDatabasePath(the_database_name) method to obtain the location that the file will be copied to. You would (at least for the first run) check to see if the database file exists in it's final location and then initiate the copy after which the database could be opened and used.
Alternately you could download it directly to the final destination rather than have an intermediate copy.
Sometimes, I'll need to add more data to the .db file. In the future, when I re-download the .db file and create a database from it, will this overwrite the existing database in the app's internal storage? Do I need to manually delete old iterations of the database?
There are various ways but basically if introducing a new file then you would likely overwrite the existing database file (stored within the App's data) at it's old location (although this isn't the only option). Although, if introducing new data rather than a new schema (the latter would likely need new code so you could utilise the database version to force a recopy).
The issue is how to know if a new file has been introduced as the database file name would, at least at the final destination, likely be the same.
Checking the size of the file may not indicate a change when there has been a change and is therefore not a failsafe option.
That is the database file is saved as chucks of pages, some of those pages will likely include free space that may be utilised when updating the database and thus the database file size remains unchanged.
You could check the last modified date of the file.
You could utilise a different file name e.g. mydbv1.db and then mydbv2.db etc.
You could utilise the user_version, care would be needed if using a subclass of SQLiteOpenHelper (as is most often the case) as this is utilised by SQLiteOpenHelper (the database version passed as the 4th paramter).
You could utilise the application_id (this is similar to user_version but is not utilised by SQLiteOpenHelper).
1-3 would require a means of persistently recording the currently used value, perhaps in a table in the database itself, perhaps an empty file in the same directory.
4 & 5 are actually stored in the database header you access the values via pragma's or programatically extract them (the latter doesn't need the file to be opened as database and would typically be less resource intensive as you only need to read the first 100 bytes to get the complete header).
Once you have detected a new version it's simply a matter of re-doing the download and copy.
The above assumes that the App has multiple users and therefore that a download file always has to exist on the host server (your website) and that you have discounted shipping the App with the database (which could simplify matters as when a new version is available you introduce a new version of the App).
The above also assumes that the database is only read by the end user. If not and the user can update data then a strategy would be needed to cater for preserving the specific user's data.
So, I just want to swap some things in the download url to make users be able to search for files in the storage. it's just that I don't want to swap the long code in the end, because then users will have to use that super long code. I have to use the url to access the files.
https://firebasestorage.googleapis.com/v0/b/socialmedia-
1df9e.appspot.com/o/images%2Flego?alt=media&token=4cc05dec-8dda-4f46-a8a7-
eb1bf916c512 ⇈ ⇈
swap this Not this
It's not supported to construct your own download URLs. You should be using the Firebase SDK to generate download URLs that are special for each file you want to download.
I am using Zumero to sync to a MS SQL server with my Android application, I have my SQLite db stored on the SD Card. When I run the sync it creates a cache file in the internal storage before updating the SQLite db. This is causing a internal storage issue and the operating system is deleting the cache file before updating the database due to running out of storage space. How can I force the app to use the SD Card for the cache file?
I have it working by replacing
context.getCacheDir().getAbsolutePath()
with
context.getExternalCacheDir().getAbsolutePath()
You'll need to use the Zumero Java files directly as part of your application (look for ZumeroClient.java, etc. in the SDK), and edit the temp path being used. Compiles these into your app instead of using zumero.jar (you'll still need the appropriate .so libraries).
Out-of-the-box, Zumero uses the cache path provided by the Android context. You'll want to edit calls to native_sync(), and replace the last parameter with a path on the SD card.
e.g.
native_sync(databasePath, encryptionKey, serverURL, dbFile, authScheme,
username, password, context.getCacheDir().getAbsolutePath());
would become
native_sync(databasePath, encryptionKey, serverURL, dbFile, authScheme,
username, password, myCacheDir);
I am integrating dropbox in my android application. The requirement is to get all file metadata. I have downloaded dropbox sdk and I am able to authenticate user's credentials as well.
I am unable to get all files using this. this provides metadata of only root folder contents
mDBApi.metadata("/", 0, null, true, null);
I need to chain the api calls to get metadata of all files and folders. Now I want to do it lazily, like get 100 files, dump the metadata in local cache and get next 100 files metadata (irrespective of file location, i.e. no matter where the file is, in root or under 10 folders)
I am using "AccessType.DROPBOX" access to get all the contents. I know that there is a parameter for specifying how many files to fetch in one go ("0" in the above statement) but I want to keep fetching metadata till all data has been received in my client. Is there a way for this or a sample code may be.
Thanks.
The Dropbox API metadata call is meant only for retrieving a single file or folder's metadata. The best practices page indicates that you should not recursively call this endpoint:
https://www.dropbox.com/developers/reference/bestpractice
You may instead be interested in using the delta call to build and maintain your local state:
https://www.dropbox.com/developers/core/api#delta
I want to place one txt file (which have insert statements) of size 273 MB, i need to know how to save that file in Phone's memory and how to access that file from my application
If i able to access that file from my application i want to insert that data in my table,already i tried to use to save the file in my application's assets folder to acess the database using database helper but i heard that assets folder can store only files of size 1 MB but my database file size is 273 MB.
For 273mb size file, I think better solution is just put the file in remote server, and using web request get data, also get the data only what you needed not all,
And put table structured database file (Without data) in asset folder and copy that file in application's internal storage then you have to download either file or data from server using web request and fill the database with it..
Update:
When you get data from server at server side make a Select query using OFFSET and LIMIT clause so its returned only bounded limited rows and make request as intervaly so there is no work load on your server and in your application..
This is my personal opinion I may be wrong on this..
If any one has a better solution then please share it..
Thanks..