Download video file from url And restrict downloaded file from outside of app

Viewed 3721

I have created android app where i play online video from url using exoplayer2 for this i have refer this Example. it working fine but now i want to add download option and also restrict that downloaded video file from other apps(downloaded video file only open inside this app like youtube downloaded videos). I had read documentation of Downloading media provided by exoplayer but failed to implement it. Someone please help me to fulfill above requirement. Or tell me any other solution to fulfill my requirement.

I have also try Android restricting downloaded files to app, This is working fine but not fulfill requirement(Downloaded video not showing in gallery or media store but file is present on this path Android/data/package_name/file_name) from where we easily access downloaded file from outside the app.

Thankyou in advance.

2 Answers

I got the solution :)

i have download video from url using Download Manager and store file on public path. This is the code

public void downloadVideo(String url) {
    Uri Download_Uri = Uri.parse(url);
    DownloadManager.Request request = new DownloadManager.Request(Download_Uri);

    //Restrict the types of networks over which this download may proceed.
    request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
    //Set whether this download may proceed over a roaming connection.
    request.setAllowedOverRoaming(false);
    // Visibility of the download Notification
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
    //Set the title of this download, to be displayed in notifications (if enabled).
    request.setTitle("Downloading");
    //Set a description of this download, to be displayed in notifications (if enabled)
    request.setDescription("Downloading File");

    //Set the local destination for the downloaded file to a path within the application's external files directory
    /*request.setDestinationInExternalFilesDir(MainActivity.this, Environment.DIRECTORY_MOVIES, "Shivam196.mp4");*/ //For private destination

    //Set the local destination for the downloaded file to a path within the application's external files directory
    request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MOVIES, "Shivam196.mp4"); // for public destination

    DownloadManager downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
    downloadID = downloadManager.enqueue(request);// enqueue puts the download request in the queue.
}

After successfully downloaded file, I have encrypt that file by passing file path on below method:

private void encryptFile(String filePath) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
    int read;
    FileInputStream fis = new FileInputStream(new File(filePath));
    File outfile = new File(Environment.getExternalStorageDirectory() + "/" + FOLDER_NAME + "/" + "test2_enc.mp4");
    if(!outfile.exists())
        outfile.createNewFile();

    FileOutputStream fos = new FileOutputStream(outfile);

    Cipher encipher = Cipher.getInstance("AES");

    KeyGenerator kgen = KeyGenerator.getInstance("AES");
    //byte key[] = {0x00,0x32,0x22,0x11,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    SecretKey skey = kgen.generateKey();

    encipher.init(Cipher.ENCRYPT_MODE, skey);
    CipherInputStream cis = new CipherInputStream(fis, encipher);

    byte[] buffer = new byte[1024]; // buffer can read file line by line to increase speed
    while((read = cis.read(buffer)) >= 0)
    {
        fos.write(buffer, 0, read);
        fos.flush();
    }
    fos.close();
    Toast.makeText(this, "File encrypted", Toast.LENGTH_SHORT).show();

    //call method for decrypt file.
    decryptFile(Environment.getExternalStorageDirectory() + "/" + FOLDER_NAME + "/" + "test_enc.mp4", skey);
}

And then decrypt the file by passing encrypted file path and secret key to below method:

private void decryptFile(String encryptFilePath, SecretKey secretKey) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
    int read;
    File outfile = new File(encryptFilePath);
    File decfile = new File(Environment.getExternalStorageDirectory() + "/" + FOLDER_NAME + "/" + "test_dec.mp4");
    if(!decfile.exists())
        decfile.createNewFile();

    FileOutputStream decfos = new FileOutputStream(decfile);
    FileInputStream encfis = new FileInputStream(outfile);

    Cipher decipher = Cipher.getInstance("AES");

    decipher.init(Cipher.DECRYPT_MODE, secretKey);
    CipherOutputStream cos = new CipherOutputStream(decfos,decipher);

    byte[] buffer = new byte[1024]; // buffer can read file line by line to increase speed
    while((read=encfis.read(buffer)) >= 0)
    {
        cos.write(buffer, 0, read);
        cos.flush();
    }
    cos.close();
    Toast.makeText(this, "File decrypted", Toast.LENGTH_SHORT).show();
}

Note: Perform encryption and description operation on background service.

Youtube Offline Features works in the following manner:

<1> Youtube app downloads the video.

<2> Saves it into youtube app's data directory in an encrypted format so other apps can't access it.

<3> Encryption is done so that video can not be played by any other apps even if the video is extracted from the youtube app data directory on rooted Android device.

<4> Video is decrypted while playing offline in the youtube app.

<5> Video is deleted after a predefined time.
Related