Here is a simple example to encrypt and decrypt a audio file in Android.
We will directly go to the implementation part.
Demo Video
You can check the demo video here.
Download Library
You can download the simple library from here.
Aim
- Download an audio file from internet.
- Encrypt and save the encrypted file in Disk, so that no one can open it.
- Decrypt the same file.
- Play the file.
Classes
For accomplishing the above tasks we have the below utility files.
- EncryptDecryptUtils – The file which encrypt and decrypts a file.
- FileUtils – This file is used for file operations.
- PrefUtils – For saving the key.
- Player – For playing the audio.
You would probably need the first three classes for encrypt and decrypting any type of files, not only the audio files.
Encryption and Decryption will return the file contents in terms of bytes.
Lets check how the EncryptDecryptUtils looks like
EncryptDecryptUtils
import android.content.Context; import android.util.Base64; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.CIPHER_ALGORITHM; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.KEY_SPEC_ALGORITHM; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.OUTPUT_KEY_LENGTH; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.PROVIDER; /** * Created by James From CoderzHeaven on 5/2/18. */ public class EncryptDecryptUtils { public static EncryptDecryptUtils instance = null; private static PrefUtils prefUtils; public static EncryptDecryptUtils getInstance(Context context) { if (null == instance) instance = new EncryptDecryptUtils(); if (null == prefUtils) prefUtils = PrefUtils.getInstance(context); return instance; } public static byte[] encode(SecretKey yourKey, byte[] fileData) throws Exception { byte[] data = yourKey.getEncoded(); SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length, KEY_SPEC_ALGORITHM); Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER); cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[cipher.getBlockSize()])); return cipher.doFinal(fileData); } public static byte[] decode(SecretKey yourKey, byte[] fileData) throws Exception { byte[] decrypted; Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM, PROVIDER); cipher.init(Cipher.DECRYPT_MODE, yourKey, new IvParameterSpec(new byte[cipher.getBlockSize()])); decrypted = cipher.doFinal(fileData); return decrypted; } public void saveSecretKey(SecretKey secretKey) { String encodedKey = Base64.encodeToString(secretKey.getEncoded(), Base64.NO_WRAP); prefUtils.saveSecretKey(encodedKey); } public SecretKey getSecretKey() { String encodedKey = prefUtils.getSecretKey(); if (null == encodedKey || encodedKey.isEmpty()) { SecureRandom secureRandom = new SecureRandom(); KeyGenerator keyGenerator = null; try { keyGenerator = KeyGenerator.getInstance(KEY_SPEC_ALGORITHM); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } keyGenerator.init(OUTPUT_KEY_LENGTH, secureRandom); SecretKey secretKey = keyGenerator.generateKey(); saveSecretKey(secretKey); return secretKey; } byte[] decodedKey = Base64.decode(encodedKey, Base64.NO_WRAP); SecretKey originalKey = new SecretKeySpec(decodedKey, 0, decodedKey.length, KEY_SPEC_ALGORITHM); return originalKey; } }
FileUtils
Helps in file related operations.
import android.content.Context; import android.support.annotation.NonNull; import android.util.Log; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.DIR_NAME; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.FILE_EXT; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.FILE_NAME; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.TEMP_FILE_NAME; /** * Created by James From CoderzHeaven on 5/6/18. */ public class FileUtils { public static void saveFile(byte[] encodedBytes, String path) { try { File file = new File(path); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file)); bos.write(encodedBytes); bos.flush(); bos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } public static byte[] readFile(String filePath) { byte[] contents; File file = new File(filePath); int size = (int) file.length(); contents = new byte[size]; try { BufferedInputStream buf = new BufferedInputStream( new FileInputStream(file)); try { buf.read(contents); buf.close(); } catch (IOException e) { e.printStackTrace(); } } catch (FileNotFoundException e) { e.printStackTrace(); } return contents; } @NonNull public static File createTempFile(Context context, byte[] decrypted) throws IOException { File tempFile = File.createTempFile(TEMP_FILE_NAME, FILE_EXT, context.getCacheDir()); tempFile.deleteOnExit(); FileOutputStream fos = new FileOutputStream(tempFile); fos.write(decrypted); fos.close(); return tempFile; } public static FileDescriptor getTempFileDescriptor(Context context, byte[] decrypted) throws IOException { File tempFile = FileUtils.createTempFile(context, decrypted); FileInputStream fis = new FileInputStream(tempFile); return fis.getFD(); } public static final String getDirPath(Context context) { return context.getDir(DIR_NAME, Context.MODE_PRIVATE).getAbsolutePath(); } public static final String getFilePath(Context context) { return getDirPath(context) + File.separator + FILE_NAME; } public static final void deleteDownloadedFile(Context context) { File file = new File(getFilePath(context)); if (null != file && file.exists()) { if (file.delete()) Log.i("FileUtils", "File Deleted."); } } }
PrefUtils
Helps in saving the values in preferences.
import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.SECRET_KEY; public class PrefUtils { public static final PrefUtils prefUtils = new PrefUtils(); public static SharedPreferences myPrefs = null; public static PrefUtils getInstance(Context context) { if (null == myPrefs) myPrefs = PreferenceManager.getDefaultSharedPreferences(context); return prefUtils; } public void saveSecretKey(String value) { SharedPreferences.Editor editor = myPrefs.edit(); editor.putString(SECRET_KEY, value); editor.commit(); } public String getSecretKey() { return myPrefs.getString(SECRET_KEY, null); } }
Player
Helps in MediaPlayer related operations.
import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Handler; import android.os.Message; import java.io.FileDescriptor; /** * Created by James from CoderzHeaven on 5/7/18. */ public class Player implements MediaPlayer.OnCompletionListener { private MediaPlayer mediaPlayer; private Handler handler; public Player(Handler handler) { this.handler = handler; } private void initPlayer() { if (null == mediaPlayer) { mediaPlayer = new MediaPlayer(); } } public void play(FileDescriptor fileDescriptor) { initPlayer(); stopAudio(); playAudio(fileDescriptor); } public void playAudio(FileDescriptor fileDescriptor) { mediaPlayer.reset(); try { mediaPlayer.setOnCompletionListener(this); mediaPlayer.setDataSource(fileDescriptor); mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mediaPlayer.prepare(); mediaPlayer.start(); } catch (Exception e) { } } private void stopAudio() { if (null != mediaPlayer && mediaPlayer.isPlaying()) { mediaPlayer.stop(); } } @Override public void onCompletion(MediaPlayer mediaPlayer) { Message message = new Message(); message.obj = "Audio play completed."; handler.dispatchMessage(message); } private void releasePlayer() { if (null != mediaPlayer) { mediaPlayer.release(); } } public void destroyPlayer() { stopAudio(); releasePlayer(); mediaPlayer = null; } }
MainActivity
Finally the main activity that does the implementation.
The layout for the activity is pasted below.
package encrypt_decrypt.coderzheaven.com.encryptdecryptandroid; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.TextView; import com.downloader.Error; import com.downloader.OnDownloadListener; import com.downloader.PRDownloader; import java.io.FileDescriptor; import java.io.IOException; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.DOWNLOAD_AUDIO_URL; import static encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.Constants.FILE_NAME; public class MainActivity extends AppCompatActivity implements OnDownloadListener, Handler.Callback { private Player player; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); player = new Player(new Handler(this)); } public final void updateUI(String msg) { ((TextView) findViewById(R.id.statusTv)).setText(msg); } public void onClick(View view) { int id = view.getId(); switch (id) { case R.id.download: downloadAudio(); break; case R.id.encrypt: if (encrypt()) updateUI("File encrypted successfully."); break; case R.id.decrypt: if (null != decrypt()) updateUI("File decrypted successfully."); break; case R.id.play: playClicked(); break; default: updateUI("Unknown Click"); } } private void playClicked() { try { playAudio(FileUtils.getTempFileDescriptor(this, decrypt())); } catch (IOException e) { updateUI("Error Playing Audio.\nException: " + e.getMessage()); return; } } private void downloadAudio() { // Delete the old file // FileUtils.deleteDownloadedFile(this); updateUI("Downloading audio file..."); PRDownloader.download(DOWNLOAD_AUDIO_URL, FileUtils.getDirPath(this), FILE_NAME).build().start(this); } /** * Encrypt and save to disk * * @return */ private boolean encrypt() { updateUI("Encrypting file..."); try { byte[] fileData = FileUtils.readFile(FileUtils.getFilePath(this)); byte[] encodedBytes = EncryptDecryptUtils.encode(EncryptDecryptUtils.getInstance(this).getSecretKey(), fileData); FileUtils.saveFile(encodedBytes, FileUtils.getFilePath(this)); return true; } catch (Exception e) { updateUI("File Encryption failed.\nException: " + e.getMessage()); } return false; } /** * Decrypt and return the decoded bytes * * @return */ private byte[] decrypt() { updateUI("Decrypting file..."); try { byte[] fileData = FileUtils.readFile(FileUtils.getFilePath(this)); byte[] decryptedBytes = EncryptDecryptUtils.decode(EncryptDecryptUtils.getInstance(this).getSecretKey(), fileData); return decryptedBytes; } catch (Exception e) { updateUI("File Decryption failed.\nException: " + e.getMessage()); } return null; } private void playAudio(FileDescriptor fileDescriptor) { if (null == fileDescriptor) { return; } updateUI("Playing audio..."); player.play(fileDescriptor); } @Override public void onDownloadComplete() { updateUI("File Download complete"); } @Override public void onError(Error error) { updateUI("File Download Error"); } @Override protected void onDestroy() { super.onDestroy(); player.destroyPlayer(); } @Override public boolean handleMessage(Message message) { if (null != message) { updateUI(message.obj.toString()); } return false; } }
Layout
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:animateLayoutChanges="true" android:orientation="vertical" android:padding="20dp" tools:context="encrypt_decrypt.coderzheaven.com.encryptdecryptandroid.MainActivity"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginBottom="20dp" android:gravity="center" android:text="[ Tap the buttons in order for the demo ]" android:textColor="@android:color/holo_red_dark" /> <Button android:id="@+id/download" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/transparent" android:gravity="left|center" android:onClick="onClick" android:text="1. Download Audio" /> <Button android:id="@+id/encrypt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/transparent" android:gravity="left|center" android:onClick="onClick" android:text="2. Encrypt Audio" /> <Button android:id="@+id/decrypt" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/transparent" android:gravity="left|center" android:onClick="onClick" android:text="3. Decrypt Audio" /> <Button android:id="@+id/play" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/transparent" android:gravity="left|center" android:onClick="onClick" android:text="4. Play" /> <TextView android:id="@+id/statusTv" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:layout_weight="0.7" android:gravity="center" android:textColor="@android:color/holo_green_dark" android:textSize="20sp" /> <TextView android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="bottom" android:layout_marginBottom="20dp" android:layout_weight="1" android:gravity="center" android:text="coderzheaven.com" /> </LinearLayout>
Source Code
You can download the complete source code from here.
thank you for the nice tutorial, please guide me how to play encrypted video in android? I want to encrypt a video file and copy to sd card, then in my app decrypt this video in the air and play in the video view.
The above code works for Video as well.
Thanks a lot for your codes.
I’m new in android, so I need help.
Are they correct?
public class Constants {
static String SECRET_KEY = “ASDFGHJKLASDFGHJ”;
static String DIR_NAME = “com….”; //My package name
static String FILE_EXT = “mp3”;
static String FILE_NAME = “1.mp3”;
static String TEMP_FILE_NAME = “tset”;
static String CIPHER_ALGORITHM = “AES”;
static String KEY_SPEC_ALGORITHM = “AES”;
static int OUTPUT_KEY_LENGTH = 128;
static String PROVIDER = “BC”;
}
My problem is about DIR_NAME.
Thanks in advance
You can have any value for DIR.
how to download pdf file in internal storage in private mode and only use by application? please reply.
You can use the get getFiles() directory.
Here is the sample code.
Make sure you give these two permissions to make it work.
Can yoh plz make tutorial on this please where we downloading the pdf file from firebase and encrypt the file after downloading and that file only open by our app only .
Thanks you so much.
Can I use this library for encrypt and decrypt video file?
Of course. you are free to use any code in this site. please give me some credit if possible.
When I click Encrypt and play the audio it sounds like a original audio. Can you tell me where the encrypted audio file is saved as well as the downloaded file? Thank you.
When you encrypt why the audio should change? When we decrypt we should get the original Audio. No one should open our encrypted audio without our key. You can change the path in the code and save anywhere you want. Now it will be in the app’s directory using getFilesPath() function.
Great tutorial.
To the point.
Thank you very much.
You are awesome.
Hi Can you guide on how to encrypt multiple images at once in a folder using the above code
You can loop through the list of files and decrypt one by one.
I have one question ?
This method also works for pdf files also : mytask is that –
I want to download the pdf file from firebase and encrypt so no one can access the file outside and the pdf file only open by the app only.
how to do it when the pdf file is download from the firebase and same time encrypt the file so that it cant be shared to anyone and only open by the app only.
Hello, nice tutorial , can you explain me why when I decrypt It’s always return a null value while my path isn’t wrong.Thank you
I clicked download audio but in all time it display download failed and another button clicked then it display whatever we have typed in code.
Are you seeing any errors in your logcat?
If anyone is facing issue with download failed from james’s code, it is because of network security config file which i haven’t found in source code so you just need to manually insert it in manifest as well as in xml folder under res directory(create xml folder if not exists). Adding network security files is so easy just google and then all set, also if website doesn’t have ssl certificate, you need to add this code :
Hi, need your help.
I have tried your code. it’s working fine with Audio/Video.
But, support it if I have a 2GB large file. then your encryption and decryption code is not working,
Could you please help me with the same?