从 url 下载视频文件并限制从应用程序外部下载文件

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

我已经创建了 android 应用程序,我在其中使用 exoplayer2 从 url 播放在线视频,为此我参考了这个 Example。它工作正常但现在我想添加下载选项并限制从其他应用程序下载的视频文件(下载的视频文件只能在此应用程序内打开,如 youtube 下载的视频)。 我已经阅读了exoplayer提供的Downloading media的文档,但未能实现它。有人请帮我完成上述要求。或者告诉我任何其他解决方案来满足我的要求。

我也尝试过 Android restricting downloaded files to app,这工作正常但不满足要求(下载的视频未显示在图库或媒体商店中但文件存在于此路径 Android/data/package_name/file_name ) 从那里我们可以轻松地从应用程序外部访问下载的文件。

提前谢谢你。

YouTube 离线功能的工作方式如下:

<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.

我得到了解决方案:)

我使用下载管理器从 url 下载视频并将文件存储在 public 路径。这是代码

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.
}

成功下载文件后,我通过以下方法传递文件路径来加密该文件:

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);
}

然后通过将加密的文件路径和密钥传递给以下方法来解密文件:

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();
}

注意:对后台服务进行加密和描述操作