微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

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

更新:

E/ExoPlayerImplInternal:播放错误 com.google.android.exoplayer2.ExoPlaybackException:源错误 在 com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:579) 在 android.os.Handler.dispatchMessage(Handler.java:102) 在 android.os.Looper.loop(Looper.java:164) 在 android.os.HandlerThread.run(HandlerThread.java:65) 引起:com.google.android.exoplayer2.source.UnrecognizedInputFormatException: 没有可用的提取器(FragmentedMp4Extractor、Mp4Extractor、FlvExtractor、FlacExtractor、WavExtractor、AmrExtractor、PsExtractor、OggExtractor、TsExtractor、ActsExtractor、Actskap3Extractor、Mp4Extractor、 ) 可以读取流。 在 com.google.android.exoplayer2.source.BundledExtractorsAdapter.init(BundledExtractorsAdapter.java:92) 在 com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1026) 在 com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:415) 在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162) 在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636) 在 java.lang.Thread.run(Thread.java:764)

解决方法

当文件存储在本地时,您可能根本不需要对其进行加密。用户或任何其他应用程序都看不到 andorid 中的本地文件存储。只有您的应用可以访问存储空间,因此您无需担心用户会读取机密数据。

编辑:因为我刚刚看到你最近对本地的评论,你的意思是在设备上。您可以将视频保存在内部存储中,除您的应用外,其他任何人都无法访问该存储空间。看看纪录片:https://developer.android.com/training/data-storage/app-specific

,

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

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,length);
                    bytesStored = cipher.doFinal(tmpBuffer,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,@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();
    }
}

我使用以下资源来制作此内容:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?