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.

 

Leave a Reply

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

 

 

 

Theme by HermesThemes

Copyright © 2018 CoderzHeaven. All Rights Reserved

Please wait...

Subscribe to our newsletter

Want to be notified when our article is published? Enter your email address and name below to be the first to know.