当前位置: 首页 > 知识库问答 >
问题:

如何在android Studio中播放本地存储的加密视频文件

阎建德
2023-03-14

我有一个使用AES算法加密的视频文件,但我需要在播放视频视图之前解密视频。问题是解密视频所需的时间太长。有什么办法我可以做到吗。

更新:

E/ExoPlayerIMIPER内部:播放错误com.google.android.exoplayer2.upstream.2. ExoPlaybackException:源错误在com.google.android.exoplayer2. ExoPlayerIMIPInternal.handle消息(ExoPlayerIMIPInternal.java:579)在android.os.Handler.dispatch消息(Handler.java:102)在android.os.Looper.loop(Looper.java:164)在android.os.HandlerThread.run(HandlerThread.java:65)由以下原因引起:com.google.android.exoplayer2.source.无法识别InputFormatException:没有可用的提取器(FragmentedMp4Extractor, Mp4Extractor, FlvExtractor, FlacExtractor, WavExtractor, AmrExtractor, PsExtractor, OggExtractor, TsExtractor, MatroskaExtractor, AdtsExtractor, Ac3Extractor, Ac4Extractor, Mp3Extractor, JpegExtractor)在com.google.android.exoplayer2.source.BundledExtractorsAdapter.init(BundledExtractorsAdapter.java:92)在com.google.android.exoplayer2.source.ProgressiveMedia$Extracting Loadable.load(ProgressiveMediaPeriod.java:1026)在com.google.android.exoplayer

共有2个答案

吕永寿
2023-03-14

给你。我不知道它是否有效,但它应该:

import android.net.Uri;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.upstream.BaseDataSource;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DataSpec;
import com.google.android.exoplayer2.upstream.FileDataSource;
import com.google.android.exoplayer2.upstream.TransferListener;
import com.google.android.exoplayer2.util.Assertions;

import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.SecretKeySpec;

import static com.google.android.exoplayer2.util.Util.castNonNull;
import static java.lang.Math.min;

public class EncryptedFileDataSource extends BaseDataSource {
    public static class EncryptedFileDataSourceException extends IOException {
        public EncryptedFileDataSourceException(Throwable cause) {
            super(cause);
        }

        public EncryptedFileDataSourceException(String message, IOException cause) {
            super(message, cause);
        }
    }

    /**
     * {@link DataSource.Factory} for {@link EncryptedFileDataSource} instances.
     */
    public static final class Factory implements DataSource.Factory {
        @Nullable
        private TransferListener listener;

        private byte[] key;
        private String transformation;

        public Factory() {
            this(null, null);
        }

        public Factory(byte[] key) {
            this(key, null);
        }

        public Factory(byte[] key, String transformation) {
            setKey(key);
            setTransformation(transformation);
        }

        public void setKey(byte[] key) {
            if (key == null) {
                return;
            }
            this.key = key;
        }

        public void setTransformation(String transformation) {
            if (transformation == null) {
                transformation = "AES/ECB/PKCS5Padding";
            }
            this.transformation = transformation;
        }

        /**
         * Sets a {@link TransferListener} for {@link EncryptedFileDataSource} instances created by this factory.
         *
         * @param listener The {@link TransferListener}.
         * @return This factory.
         */
        public Factory setListener(@Nullable TransferListener listener) {
            this.listener = listener;
            return this;
        }

        @Override
        public EncryptedFileDataSource createDataSource() {
            EncryptedFileDataSource dataSource = new EncryptedFileDataSource(key, transformation);
            if (listener != null) {
                dataSource.addTransferListener(listener);
            }
            return dataSource;
        }
    }

    @Nullable
    private RandomAccessFile file;
    @Nullable
    private Uri uri;

    private long bytesRemaining;
    private boolean opened;

    private byte[] key;
    private String transformation;
    private Cipher cipher;

    private byte[] tmpBuffer;

    private EncryptedFileDataSource(byte[] key, String transformation) {
        super(false);

        setKey(key);
        setTransformation(transformation);
    }

    public void setKey(byte[] key) {
        this.key = key;
    }

    public void setTransformation(String transformation) {
        this.transformation = transformation;
    }

    @Override
    public long open(@NonNull DataSpec dataSpec) throws EncryptedFileDataSourceException {
        try {
            byte[] key = this.key;
            String transformation = this.transformation;

            Uri uri = dataSpec.uri;
            this.uri = uri;

            transferInitializing(dataSpec);

            if (key != null && transformation != null) {
                SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
                cipher = Cipher.getInstance(transformation);
                cipher.init(Cipher.DECRYPT_MODE, keySpec);
            }

            this.file = openLocalFile(uri);
            file.seek(dataSpec.position);
            bytesRemaining = dataSpec.length == C.LENGTH_UNSET ? file.length() - dataSpec.position
                    : dataSpec.length;
            if (bytesRemaining < 0) {
                throw new EOFException();
            }
        } catch (IOException
                | NoSuchPaddingException
                | NoSuchAlgorithmException
                | InvalidKeyException e) {
            throw new EncryptedFileDataSourceException(e);
        }

        opened = true;
        transferStarted(dataSpec);

        return bytesRemaining;
    }

    @Override
    public int read(@NonNull byte[] buffer, int offset, int readLength) throws EncryptedFileDataSourceException {
        if (readLength == 0) {
            return 0;
        } else if (bytesRemaining == 0) {
            return C.RESULT_END_OF_INPUT;
        } else {
            int bytesRead, bytesStored;
            try {
                int length = (int) min(bytesRemaining, readLength);

                Cipher cipher = this.cipher;
                if (cipher != null) {
                    tmpBuffer = resize(tmpBuffer, length);
                    bytesRead = castNonNull(file).read(tmpBuffer, 0, length);
                    bytesStored = cipher.doFinal(tmpBuffer, 0, length, buffer, offset);
                } else {
                    bytesStored = bytesRead = castNonNull(file).read(buffer, offset, length);
                }
            } catch (IOException
                    | BadPaddingException
                    | IllegalBlockSizeException
                    | ShortBufferException e) {
                throw new EncryptedFileDataSourceException(e);
            }

            if (bytesRead > 0) {
                bytesRemaining -= bytesRead;
                bytesTransferred(bytesRead);
            }

            return bytesStored;
        }
    }

    @Nullable
    @Override
    public Uri getUri() {
        return uri;
    }

    @Override
    public void close() throws EncryptedFileDataSourceException {
        uri = null;
        try {
            if (file != null) {
                file.close();
            }
        } catch (IOException e) {
            throw new EncryptedFileDataSourceException(e);
        } finally {
            file = null;
            key = null;
            transformation = null;
            cipher = null;
            if (opened) {
                opened = false;
                transferEnded();
            }

            byte[] tmpBuffer = this.tmpBuffer;
            this.tmpBuffer = null;
            if (tmpBuffer != null) {
                for (int i = tmpBuffer.length - 1; i >= 0; i -= 2) {
                    tmpBuffer[i] = (byte) 0;
                }
            }
        }
    }

    static byte[] resize(byte[] b, int newLen) {
        if (newLen < 0) return b;
        if (b == null || b.length < newLen) {
            return new byte[newLen];
        } else return b;
    }

    private static RandomAccessFile openLocalFile(Uri uri) throws FileDataSource.FileDataSourceException {
        try {
            return new RandomAccessFile(Assertions.checkNotNull(uri.getPath()), "r");
        } catch (FileNotFoundException e) {
            if (!TextUtils.isEmpty(uri.getQuery()) || !TextUtils.isEmpty(uri.getFragment())) {
                throw new FileDataSource.FileDataSourceException(
                        String.format(
                                "uri has query and/or fragment, which are not supported. Did you call Uri.parse()"
                                        + " on a string containing '?' or '#'? Use Uri.fromFile(new File(path)) to"
                                        + " avoid this. path=%s,query=%s,fragment=%s",
                                uri.getPath(), uri.getQuery(), uri.getFragment()),
                        e);
            }
            throw new FileDataSource.FileDataSourceException(e);
        }
    }
}

这样使用:

public void playVideo(Uri uri, byte[] key, @Nullable String transformation) {
    playVideo(MediaItem.fromUri(uri), key, transformation);
}

public void playVideo(MediaItem media, byte[] key, @Nullable String transformation) {
    ExoPlayer player = new SimpleExoPlayer.Builder(this).build();
    playerView.setPlayer(player);
    
    try {
        DataSource.Factory dataSourceFactory = new EncryptedFileDataSource.Factory(key, transformation);
        ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
        
        ProgressiveMediaSource.Factory progressiveFactory = new ProgressiveMediaSource.Factory(
                dataSourceFactory,
                extractorsFactory
        );

        ProgressiveMediaSource mediaSource = progressiveFactory.createMediaSource(media);
        player.setMediaSource(mediaSource);
        //player.setMediaSource(mediaSource, startPositionMs: long);
        //player.setMediaSource(mediaSource, resetPosition: boolean);
        player.setPlayWhenReady(true);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

我使用了以下来源:

  • https://github.com/google/ExoPlayer/blob/4364b9150f236813a2070fc79d3bcb76e11969ac/library/core/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java
  • Android exoplayer:本地播放AES加密视频
南宫森
2023-03-14

当文件存储在本地时,您可能根本不需要对其进行加密。andorid中的本地文件存储对用户或任何其他应用程序都不可见。只有你的应用程序可以访问存储,所以你不需要担心用户阅读机密数据

编辑:正如我刚刚看到您最近对本地的评论,您的意思是在设备上。您可以将视频保存在内部存储中,除了您的应用程序之外,没有其他内容可以访问。看看纪录片:https://developer.android.com/training/data-storage/app-specific

 类似资料:
  • 在linux盒子上,我有一个用openssl加密的MP4视频: 请注意,这是一个练习,算法的强度并不重要。 该文件被发送到Android应用程序,我正在尝试使用ExoPlayer播放它。 我之前已经对文本文件进行了一些测试,以确保解密工作正常 关于ExoPlayer,在AiscipherDataSource、AiscipherDataSink、SimpleCache等之间有点势不可挡。我无法找到一

  • 我一直试图在ShakaPlayer中播放加密的。WebM媒体文件,但没有太多成功,我在这里寻求任何经历过这一点的人的建议。如果这个很棒的开发人员社区有人能在这里指导我,那就太好了。 第1轮-我所尝试的(编码和虚线): 使用ffmpeg.将.mp4文件编码为多流Video.webm(VP9)&单流Audio.webm(Vorbis)文件 使用webm_tools/webm_dash_manifest

  • 问题内容: 我有问题 我想在pygame中加载和播放视频,但它没有开始。我唯一看到的是黑屏。这是我的代码: 你能帮助我吗?? 问题答案: 您实际上并没有将其发送到屏幕。您也没有使用时钟对象,因此它将尽可能快地播放。尝试这个: 我只是从评论中提供的链接中获得了MELT.MPG。您应该能够简单地为您要播放的实际MPG切换出该字符串,它就可以工作…也许。

  • 我已经成功地上传了一个音频文件(3GP)到谷歌驱动器。 现在我希望能够在应用程序中播放该文件。 Google Drive API只允许获取存储在那里的文件的输入流。 在我的情况下,输入的所有MediaPlayer功能都不可用,这只是InputSteam: 我知道我可以将文件从谷歌驱动器保存到缓存中并播放它,但我想避免存储处理,并在飞行中播放文件。 我试图搜索这个问题,只发现可能使用AudioTra

  • 我检查过: 我查看了这个链接,上面有一个答案,说你必须将视频转换成块,并将块保存到firebase存储区,然后加载它们: 但我在这里迷失了: 谢谢你的努力。

  • 问题内容: 我要实现以下目标。 目的是使用户能够从他/她的硬盘驱动器中选择文件。 不上传的原因当然是传输成本和存储配额。没有理由保存文件。 可能吗? 问题答案: 可以播放本地视频文件。 通过元素选择文件时: “更改”事件被触发 从获取第一个File对象 制作指向File对象的对象URL 将对象URL设置为属性 靠后看