I have an android application which downloads and play mp3 files. But I want to encrypt audio files while downloading and then decrypt to play it. I have already checked everywhere in the internet but did not find any solution. Could anyone please help me how to encrypt audio files while downloading and then decrypt during playing Here is my code to download the files
private void download() {
if (Constant.arrayList_play.size() > 0) {
File root = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Myapp/cache");
if (!root.exists()) {
root.mkdirs();
}
File file = new File(root, Constant.arrayList_play.get(viewpager.getCurrentItem()).getMp3Name() + ".mp3");
if (!file.exists()) {
String url = Constant.arrayList_play.get(viewpager.getCurrentItem()).getMp3Url();
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription(getResources().getString(R.string.downloading) + " - " + Constant.arrayList_play.get(viewpager.getCurrentItem()).getMp3Name());
request.setTitle(Constant.arrayList_play.get(viewpager.getCurrentItem()).getMp3Name());
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationUri(Uri.parse("file://" + Environment.getExternalStorageDirectory().getAbsolutePath() + "/Myapp/cache/" + Constant.arrayList_play.get(viewpager.getCurrentItem()).getMp3Name() + ".mp3"));
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
new AsyncTask<String, String, String>() {
@Override
protected String doInBackground(String... strings) {
String json = JsonUtils.getJSONString(Constant.URL_DOWNLOAD_COUNT + Constant.arrayList_play.get(viewpager.getCurrentItem()).getId());
Log.e("aaa - ", json);
return null;
}
}.execute();
Toast.makeText(MainActivity.this, getResources().getString(R.string.downloading), Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(MainActivity.this, getResources().getString(R.string.already_download), Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(MainActivity.this, getResources().getString(R.string.no_song_selected), Toast.LENGTH_SHORT).show();
}
}
So could you please help me with a code.
I have found a solution to my question and have been using it in my app since many days without any problem so I think it is good to answer my own question also as many users had asked for solution in comments. So just follow the below codes-
//Downloading and encrypting the audio
AesCipherDataSink encryptingDataSink = new AesCipherDataSink(
Util.getUtf8Bytes("4J95qN8RxBP8hTpk"),
new DataSink() {
private FileOutputStream fileOutputStream;
@Override
public void open(DataSpec dataSpec) throws IOException {
fileOutputStream = new FileOutputStream(file);
}
@Override
public void write(byte[] buffer, int offset, int length) throws IOException {
fileOutputStream.write(buffer, offset, length);
}
@Override
public void close() throws IOException {
fileOutputStream.close();
}
});
// Push the data through the sink, and close everything.
encryptingDataSink.open(new DataSpec(Uri.fromFile(file)));
URL downloadURL = new URL(strings[0]);
HttpURLConnection connection = (HttpURLConnection) downloadURL.openConnection();
connection.setChunkedStreamingMode(0);
connection.setDoInput(true);
connection.connect();
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
return "Server error";
}
InputStream inputStream = connection.getInputStream();
byte[] buffer = new byte[1024];
int newLength;
while ((newLength = inputStream.read(buffer)) > 0) {
encryptingDataSink.write(buffer, 0, newLength);
}
encryptingDataSink.close();
inputStream.close();
//decrypting and playing the audio
DataSource.Factory factory =
new CustomDataSourceFactory(
context,
new OkHttpDataSourceFactory(new OkHttpClient(), Util.getUserAgent(context,
context.getResources().getString(R.string.app_name)))
);
MediaSource videoSource =
new ProgressiveMediaSource.Factory(factory)
.createMediaSource(Uri.parse(tempFile.getAbsolutePath()));
exoPlayer.addMediaSource(videoSource);
//CustomDataSourceFactoryClass
public class CustomDataSourceFactory implements DataSource.Factory {
private final Context context;
private final DataSource.Factory baseDataSourceFactory;
public CustomDataSourceFactory(Context context, DataSource.Factory baseDataSourceFactory) {
this.context = context.getApplicationContext();
this.baseDataSourceFactory = baseDataSourceFactory;
}
@Override
public DataSource createDataSource() {
return new CryptedDefaultDataSource(context, baseDataSourceFactory.createDataSource());
}
}
//CryptedDafaultDataSource
public class CryptedDefaultDataSource implements DataSource {
private final List<TransferListener> transferListeners;
private final DataSource baseDataSource;
private @Nullable
DataSource fileDataSource,aesCipherDataSource,dataSource;
private Context context;
CryptedDefaultDataSource(Context context, DataSource baseDataSource) {
this.context=context;
this.baseDataSource = Assertions.checkNotNull(baseDataSource);
transferListeners = new ArrayList<>();
}
@Override
public void addTransferListener(TransferListener transferListener) {
baseDataSource.addTransferListener(transferListener);
transferListeners.add(transferListener);
maybeAddListenerToDataSource(fileDataSource, transferListener);
maybeAddListenerToDataSource(aesCipherDataSource, transferListener);
}
@Override
public long open(DataSpec dataSpec) throws IOException {
Assertions.checkState(dataSource == null);
if (Util.isLocalFileUri(dataSpec.uri)) {
dataSource = getCryptedDataSource(getFileDataSource());
} else {
dataSource = getCryptedDataSource(baseDataSource);
}
return dataSource.open(dataSpec);
}
@Override
public int read(byte[] buffer, int offset, int readLength) throws IOException {
return Assertions.checkNotNull(dataSource).read(buffer, offset, readLength);
}
@Nullable
@Override
public Uri getUri() {
return dataSource == null ? null : dataSource.getUri();
}
@Override
public Map<String, List<String>> getResponseHeaders() {
return dataSource == null
? DataSource.super.getResponseHeaders()
: dataSource.getResponseHeaders();
}
@Override
public void close() throws IOException {
if (dataSource != null) {
try {
dataSource.close();
} finally {
dataSource = null;
}
}
}
private DataSource getFileDataSource() {
if (fileDataSource == null) {
fileDataSource = new FileDataSource();
addListenersToDataSource(fileDataSource);
}
return fileDataSource;
}
private DataSource getCryptedDataSource(DataSource upstreamDataSource) {
if (aesCipherDataSource == null) {
aesCipherDataSource = new AesCipherDataSource("4J95qN8RxBP8hTpk".getBytes(),upstreamDataSource);
addListenersToDataSource(aesCipherDataSource);
}
return aesCipherDataSource;
}
private void addListenersToDataSource(DataSource dataSource) {
for (int i = 0; i < transferListeners.size(); i++) {
dataSource.addTransferListener(transferListeners.get(i));
}
}
private void maybeAddListenerToDataSource(
@Nullable DataSource dataSource, TransferListener listener) {
if (dataSource != null) {
dataSource.addTransferListener(listener);
}
}
}