How to encrypt and decrypt an audio file in Android?

By | May 8, 2018

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.

21 thoughts on “How to encrypt and decrypt an audio file in Android?

  1. arsalan

    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.

    Reply
  2. Monir

    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

    Reply
  3. Riya soni

    how to download pdf file in internal storage in private mode and only use by application? please reply.

    Reply
    1. James Post author

      You can use the get getFiles() directory.
      Here is the sample code.

      public void writeFileOnInternalStorage(Context mContext,String sFileName, String sBody){      
          File file = new File(mcoContext.getFilesDir(),"mydir");
          if(!file.exists()){
              file.mkdir();
          }
      
          try{
              File pdfFile = new File(file, sFileName);
              FileWriter writer = new FileWriter(pdfFile);
              writer.append(sBody);
              writer.flush();
              writer.close();
      
          }catch (Exception e){
              e.printStackTrace();
          }
      }
      

      Make sure you give these two permissions to make it work.

      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
      
      Reply
      1. Abhay rana

        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.

        Reply
    1. James Post author

      Of course. you are free to use any code in this site. please give me some credit if possible.

      Reply
  4. Chetan

    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.

    Reply
    1. James Post author

      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.

      Reply
  5. Deep Dave

    Great tutorial.
    To the point.
    Thank you very much.
    You are awesome.

    Reply
  6. remy

    Hi Can you guide on how to encrypt multiple images at once in a folder using the above code

    Reply
    1. James Post author

      You can loop through the list of files and decrypt one by one.

      Reply
  7. Abhay rana

    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.

    Reply
  8. abhay rana

    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.

    Reply
  9. steeve

    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

    Reply
  10. Coding star

    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.

    Reply
  11. john coding help

    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 :

    Reply
  12. Mayank Langalia

    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?

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *