3

I am downloading audio files MP3/ OGG programmatically from user provided URLs. I further would proceed to set the downloaded files as ringtone/alarmtone. However, I need to programmatically verify that the file downloaded is a valid MP3/OGG file and is playable. What way can I make sure that the file that has been downloaded is a valid MP3/OGG file and not a junk header from a fake URL.

Code I am using to download :

try {
        URL url = new URL(link);
        httpConn = (HttpURLConnection) url.openConnection();
        httpConn.setRequestMethod("GET");
        httpConn.setReadTimeout(20000);
        httpConn.setConnectTimeout(10000);
        httpConn.connect();
        int responseCode = httpConn.getResponseCode();
        if (responseCode != HttpURLConnection.HTTP_OK) {
            Log.i(TAG, "http response error code "+responseCode+" for "+name);
            return -1;
        }

        int lenghtOfFile = httpConn.getContentLength();
        Log.d(TAG, "Length of file to download: " + lenghtOfFile + " for " + name + " id_download "+id_download);
        if (lenghtOfFile == -1) {
            return -1; // no length to download
        }
        // input stream to read file - with 8k buffer
        input = new BufferedInputStream(httpConn.getInputStream(),1000000);

        // Delete the outfile first
        File deleteFile = new File(outfile);
        if (deleteFile.exists()) {
            if (deleteFile.delete())
                Log.i(TAG, "File deleted " + outfile);
            else
                Log.i(TAG, "File could'nt be deleted " + outfile);
        }

        output = new FileOutputStream(outfile);
        byte data[] = new byte[1000000];

        long total = 0;
        int progress = 0;
        long mLastUpdate = 0;

        int count = 0;
        while ((count = input.read(data)) != -1) {
            total += count;
            progress = (int) ((total * 100) / lenghtOfFile);
            Log.d(TAG, name + " progress " + progress+"  count "+count+" total "+total);
            output.write(data, 0, count);
            if (System.currentTimeMillis() - mLastUpdate > 1000) {
                mLastUpdate = System.currentTimeMillis();
            }
        }

        output.flush();
    } catch (Exception e) {
        Log.e(TAG, "Exception in downloadUrl() " + e + " for " + name + "  " + id_download + "  "+task_id);
        return -1;
    } finally {
        try {
            if (output != null) {
                output.close();
            }
            if (input != null) {
                input.close();
            }
            if (httpConn != null) {
                httpConn.disconnect();
            }
        } catch (Exception ex) {
            Log.e(TAG,"Exception in close "+ex);
        }
    }
Nikita
  • 77
  • 10
  • What are you using to download? Does it have a listener or callback to let you know what the download is complete? – Doug Stevenson Feb 25 '16 at 05:45
  • post your download code – Ajay Pandya Feb 25 '16 at 05:47
  • I am asking the user to provide the name and url in a web server, and downloading all the files in one go. I have written an API to download the files, which returns 1 on success and 0 on failure. After the files have been downloaded successfully, I proceed to set them as ringtones. – Nikita Feb 25 '16 at 05:48
  • you are looking for idea? how can do this? – Ajay Pandya Feb 25 '16 at 05:58
  • @Ajay Updated the question with the download code. Yes ,I am looking for a way to validate the downloaded MP3/OGG files. – Nikita Feb 25 '16 at 05:59
  • ok so get your downloaded file name and check end with extension because you can not physically check without play it so you can check valid extension – Ajay Pandya Feb 25 '16 at 06:00
  • you can get reference from this code https://github.com/smanikandan14/ThinDownloadManager – Ajay Pandya Feb 25 '16 at 06:06
  • Checking for extension using URL is not reliable. Sometimes the API returns faulty results. Any other method you can suggest ? – Nikita Feb 25 '16 at 06:10
  • first you got download complete event? – Ajay Pandya Feb 25 '16 at 06:10
  • Yes. So for example I am giving a fake URL, that too is downloading some junk data and putting it to the outfile i created. That way i am not able to filter out valid url having an MP3/OGG file and some random url say "stackoverflow.com". The length to download for stackoverflow.com wont be -1... – Nikita Feb 25 '16 at 06:14
  • look over this solution http://stackoverflow.com/a/11360513/3514144 – Ajay Pandya Feb 25 '16 at 06:14
  • From your current problem i can say there is not pre-define algorithm which will identify url and marking as junk or valid as well as not guaranteed about downloaded file content other than length. – Ajay Pandya Feb 25 '16 at 06:22
  • Yes, and i had seen the solution in the link provided by you. I ll have to dig in deeper to see how to code it. – Nikita Feb 25 '16 at 06:32
  • Hope you will create algorithm and post here so i also can get help i have same situation but for video content – Ajay Pandya Feb 25 '16 at 06:33

2 Answers2

1

You can check for the End of the download stream, if it is called, its an indication, your files downloaded with complete length. Accept this answer if it works for you? Thanks

  • I dont think so this will work for fake URLs. a random link with random data will also send end of download stream. what i want is to validate is a downloaded file is a playable mp3/ogg. – Nikita Feb 25 '16 at 06:19
  • In that case you can try installing the file say if it is APK and check for result. same for mp3/ogg file you can try playing to make sure it is not corrupted file. – rahul ahuja Feb 25 '16 at 06:23
1

I resolved the issue by using MediaMetadataRetriever classe's API "extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)". This returns a valid duration if its a valid mp3/ ogg file. Else I catch a runtime exception and return from my API.

Nikita
  • 77
  • 10
  • This only gives the duration set in the media's metadata, irrespective of the completeness of the media. i.e. If say a music file is not completely downloaded, yet this key shall return the duration of the complete media. – Sagar Nov 29 '17 at 05:06