Store mp3 files in a database? - android

I am currently creating a mobile android app in Android Studio for my church.
My app is basically a Bible which verses are linked to mp3 audio explanations from my preacher; however, I don't know whether I should save these mp3 files stored locally in the phone of the user or store them in a database.
I have been reading some things about databases and found out that SQLite is good, but stores the database locally, which is not what I want.
How can I solve this problem?
Every verse in the Bible is linked to a specific mp3 audio sermon/explanation from my preacher.

Relational Databases aren't necessarily meant to store actual files. Sure, you could store BLOB binary types, but I wouldn't suggest it. That's what file servers are for. For example, Amazon S3, or Firebase Storage.
You can store the URL to a file in the database, but store the actual file on a remote system to keep your applications size small.
You can cache the resources on disk lazily as the user reads said passage, or set up a system to stream them. That'd require more effort than just downloading the whole file once per device, though

I could not understand a lot from you question as there are too few details. If I understood correctly the question, the best way to implement this is to upload the mp3 you want to the server and in the android app play the file from the server (make a request to the web). In this case you will save to the database only the name of your mp3 and the link from the server to this file.
Another approach would be to convert your mp3 to base64 and save it in SQLite as a text datatype (as base64 string may have more than 256 chars long) and when needed you can decode it but it will be much slower than hosting everything to cloud
try {
MediaPlayer player = new MediaPlayer();
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource("http://xty/MRESC/images/test/xy.mp3");
player.prepare();
player.start();
} catch (Exception e) {
// TODO: handle exception
}

Related

How can I create a sqlite database file to be returned by a webservice

I want to create a sqlite database file in a web service, so I dont have to read a json in the android device and wait for it to read the json, convert it to an object and then insert it to the database.
When the json is huge, with a lot of data, that process its to long for be waiting in an android device.
I would like to generate the database file of sqlite in the webservice, so that, instead of returning the json, it returns the sqlite database, and in android, I just need to save the database, so that, it is ready to use.
That would save a lot of time!
SQLite have libraries for almost any kind of server side language.
SQLite db is just a file so after is created you shall compress is in a zip and use volley library to dl the file over http.
Decompress the zip and connect to it.
I have no idea about which kind of data and which amount you need to transfer but if the data is organised properly the processing should be so long. Also you have to take in consideration that using JSON you can "ask" to receive only updates (delta) and this is something that is not possible if you download all the db each time.
Update: for this kind a data I would go to a different approach. Use docs from google publishing api to upload every specific period of time the db in an extension pack for your app. so most of the dl'ing process is even before the "install" on the device itself. When the app is first running will contact your server and get the latest updates since the db was created (I suppose that even that is a week you are talking about less than a hundred rows)...

How can I let a web view-based Android app store large amounts of files on disk?

I’m making an Android app that lets users store a bunch of video files on disk after retrieving them from an RSS feed. The app will run in a web view. I’m fetching the videos with XHR requests.
How can I send a message from javascript to java containing the data for the downloaded files?
I mean … I could store the files within indexdb within the web view browser. However, browser cache APIs like app cache and indexdb have strict quotas. I don’t think I can store many video files within those quotas.
And it also looks like the quota updater API is deprecated, so I can’t alter web storage quotas: http://developer.android.com/reference/android/webkit/WebStorage.QuotaUpdater.html
It seems like my only alternative is to send file data from the web view as a message for java code to handle (and store the file on local disk). Later, I can have java tell the web view that it had previously stored data. How can I send such a message using the android API?
I’m fetching the videos with XHR requests
Off the cuff, I wouldn't. Usually video files are large, and if you really want them downloaded, you can't just do that from an activity, whether powered by a WebView or not.
It seems like my only alternative is to send file data from the web view as a message for java code to handle (and store the file on local disk). Later, I can have java tell the web view that it had previously stored data. How can I send such a message using the android API?
Use addJavascriptInterface() on the WebView to inject a Java object into the JavaScript environment of the WebView. On that Java object, have a method that will download the video file, using a Service (perhaps an IntentService) or DownloadManager, given the URL to the file. Not only will this solve your issue of how to get the file stored locally on the device, but it is more likely that the video will actually successfully download if the user navigates away from your app while the download is going on.

The best way to get song from remote database

I was wondering what is the best way to play song without having connection network ?
Explanation :
I have an application that play some songs. I can play a song whenever I want, even if I m in a tunnel or in a place where I dont have a network connection.
What is the best way to manage it ?
Does sqlite sufficient to save a song to a binary format ?
Should I store the music in a directory and register the sound path ?
Thanks for advance
You can store song meta-data in SQLite (like: song list, titles, authors...) but storing actual audio data in it is a bad idea. The overhead of storing BLOBs in a database is pretty big. And there is no way to play audio directly off database, so I would have to unload it all to memory or create temporary file.
I suggest you to relay on normal files located on external storage.

Android: How safe is database packed with application

I want to know how safe it is to pack the database with the application in android. Can the database be easily accessed by the users? As the database that I have will have data which I dont want to be hacked by users for misuse, what is the best way to protect the database in mobile apps?
Also my application would use web service(contacting my own website) e.g. http:\www.mysite.com/services/xxx
My site will in turn return some data to the mobile app. If someone decompiles the java code(in apk), he will easily get access to the URL i am using for web service. How can i protect my data on website to be attacked by malicious users. If anyone gets to know the URL, he can simply type that URL in browser and get all data in json format which i dont want as that data can be quite sensitive. Even if I keep it encoded, then the user can get to know the encoding from the java code(which he gets after decompiling apk).
How to keep my DB safe from being misused?
If my application is to show the local places like restaurants, bars etc on mobile should i always fetch them from the website using web service or provide a local database with these details so that information can be fetched quickly. In this case , I can provide a UPDATE web servcie which will update the local database. But security of local DB is of great concern to me.
Can anyone please suggest where to keep the DB and how to safeguard it?
Rgds,
Sapan
Local databases and your apk file can be read by any rooted device easily. This tool can even decompile your resources as explained in this youtube tutorial (I never tried that myself actually).
So you would have to store your data encrypted in your database and decrypt it form your application code to be sure that noone can access it by simply getting the database form the data directory of his device.
You shouldn't put your sensitive data (like passwords etc) in the resource folder, because it can be decompiled, put it in your code.
Now some words to your JSON API. Hiding the URL is not enough, since the user can track your requests easily by a sniffer and get that anyway. You should provide a authentication mechanism to protect unauthorized access and also protect your communication by SSL. (E.g. using HTTP authentication - makes only sense when your server provides SSL.)
This are the things you should think about and decide yourself how sensitive your data actually is.
As far as I understand you're going to:
Pack initial DB in your APK file (say with res/asset folder)
During first run explode DB file from res/asset to application data folder
Then from to time fetch data into DB from website/webservice
In this case there are basically 2 vulnerabilities (stored data I mean):
Initial DB image, since it's packed with APK (which is in real life just ZIP archive), so anyone can unpack and see what's packed in your DB
DB file stored in application data folder (usually /data/data/MY_APPLICATION_PACKAGE/databases). This folder is accessible on rooted device, so again your data can easily be screened
The only option to be secured is to encrypt your database content. Easiest way to do it to store sensitive data in BLOBs (in form of XML of JSON) and encrypt/decrypt those BLOBs after/before actual usage of certain records.
Myself personally did it in my app - and it works well.
check this links for protecting your apk file for decompile
How to make apk Secure. Protecting from Decompile
Protecting Android apk to prevent decompilation, network sniffing etc
decompiling DEX into Java sourcecode

Stream audio from SQLite db

I have an SQLite db, and it has audio files in it stored as blobs.
Is it possible in android (or anywhere) to stream media from a db?
I would recommend not storing the audio data in the database. The memory issues mentioned earlier can lead to huge amounts of GC thrashing which can make the system non-responsive for seconds or more at time.
The typical approach involves a handful of steps.
Store the audio in a file somewhere in your application's directory.
Create two columns in your database. One column (called anything you like) contains a "content://" URL that references the data. Seeing a "content://" URL is a trigger to the system to then look up the contents of the "_data" column in the same row. The contents of that column should be the full path to the file.
The system then transparently reads that file, and presents it to whichever code actually requested the content.
I've got some example code for doing this with images -- obviously, it's not quite the same, but I can walk through it here and you should get the gist.
The specific problem I was trying to solve was storing album artwork for a track that's stored off the device. I wanted to be able to show the album artwork in a list, and cache it locally on the device so that repeatedly scrolling through it is fast and does involve repeated network fetches for the same data.
I have an albums database, with various columns that get lazily populated from a remote server. I implement this database using the ContentProvider framework. There's a lot of great information about ContentProviders at http://developer.android.com/guide/topics/providers/content-providers.html, and you should read that first so that the rest of this makes sense.
The files involved are (note: I've linked to specific points in the tree because this is a work in progress and I want the line number references I give you to be stable):
https://github.com/nikclayton/android-squeezer/blob/02c08ace43f775412cc9715bf55aeb83e7b5f2dc/src/com/danga/squeezer/service/AlbumCache.java
This class defines various constants that are used elsewhere, and is pretty idiomatic for anything that's implemented as a ContentProvider.
In this class, COL_ARTWORK_PATH is the column that's going to contain the content:// URL.
https://github.com/nikclayton/android-squeezer/blob/02c08ace43f775412cc9715bf55aeb83e7b5f2dc/src/com/danga/squeezer/service/AlbumCacheProvider.java
This is the implementation of the ContentProvider. Again, this is pretty idiomatic for ContentProviders that are wrapping SQLite databases. Some points of interest:
429: albumListCallback()
This code is called whenever the app receives data about an album from the remote server (that's specific to my app, and not relevant to your problem). By this point the data has been wrapped up as a list of SqueezerAlbums, so this code has to unpack that data and turn it in to rows in the database.
456: Here we call updateAlbumArt with enough data that it can do a remote fetch of the album artwork (and I've just realised looking at this code that I can make this more efficient because it's updating the database more often than it should. But I digress).
475: updateAlbumArt()
This has to fetch the remote image, resize it, store both the original and resized versions in the filesystem (why both? Because I haven't finished this, and there will be code to select the correct cached size later).
This creates a cache directory as necessary, downloads the remote image, resizes it, and saves it to the files.
535: This is the bit you're probably particularly interested in. This creates a content:// URL (using the constants in AlbumCache.java) that references the data, and puts that in COL_ARTWORK_PATH. Then it puts the absolute path to the file in the _data column.
571: openFile()
You must implement this. Users of the ContentProvider will call openFile() when they want to open the file in the database. This implementation uses openFileHelper(), which is the code that looks up the value in the _data column, opens that file, and returns a ParcelFileDescriptor to the caller.
As you may just have realised, your open implementation of openFile() doesn't have to do this -- you could use another column name, or perhaps you have a way of going straight from the URL to the file in the filesystem. This does seem to be a very common idiom though.
Assuming you've done something like that, and now have a ContentProvider for your database, to actually access the image, your application will need to have generated a URI that references a given piece of content by it's ID. The code in the app to open the file looks like this:
Inputstream f = this.getContentResolver().openInputStream(theUri);
which ends up calling your implementation of openFile(), which ends up calling openFileHelper(), which finally gets to the right file in the filesystem. One other advantage of this approach is that openFile() is called in your application's security domain, so it can access the file, and, if implemented correctly, your ContentProvider can be called by completely different applications if you make the URLs that it responds to publicly known.
If you are storing the actual audio data in the database in a format that the Android audio system can natively interpret (i.e. mp3, 3gpp, ogg) then one way you could do it is to implement a web server in a Service, and have that Service open the SQLite database, fetch the blob using Cursor.getBlob and then feeding that Blob out to a MediaPlayer instance through the web server by wrapping the byte array with a ByteArrayInputStream. I've seen implementations like this done (in those cases it was from file, not db but the same principles apply).
Alternatively you could use AudioTrack, translate the audio if its not in PCM format and then play it and handle the audio management yourself: probably a lot more work but more efficient.
Note that this will be EXTREMELY memory-intensive and will probably perform poorly: for a 5mb MP3 you'd basically have to hold the entire thing in memory since it doesn't appear that Android's SQLite interface gives you a stream interface to blobs. If you are loading multiple media files, then...bad things happen.

Categories

Resources