2

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.

Shivam Jamaiwar
  • 554
  • 1
  • 4
  • 14

2 Answers2

2

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.

Shivam Jamaiwar
  • 554
  • 1
  • 4
  • 14
0

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.
Krishna Sony
  • 1,316
  • 11
  • 24
  • Yes, i have already try to encrypt video file Using this (https://stackoverflow.com/questions/9496447/encryption-of-video-files) reference but it take to much time to encrypt and decrypt video i.e video of 85 mb size, take more than 20 mins. – Shivam Jamaiwar May 16 '20 at 10:51
  • Use the Work Manager library to do this type of task in the background. So that it can not violate your UI – Krishna Sony May 16 '20 at 10:54