I am building a app form where users can download a video but can not play using inbuild video player.
Only from within the app user can play it.
I tried the following:
Downloaded the video using android downloadManager to download folder.
then I am encrypting the video using android cipher and algo AES.
then I am deleting the origin downloaded video.
I have implemented videoview,to play video.
from app I am de-cipering the video and then plugging it into video view source.
but it's not working.
All my videos are in .mp4 format.
Here is the code for ciphering and de-cyphering video(taken on another stackover answer, but don't have link anymore)
try{
FileInputStream fis = new FileInputStream(new File(c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME))));
File outfile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/appvideo/1.mp4");
int read;
if(!outfile.exists())
outfile.createNewFile();
File decfile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/appvideo/2.mp4");
if(!decfile.exists())
decfile.createNewFile();
FileOutputStream fos = new FileOutputStream(outfile);
FileInputStream encfis = new FileInputStream(outfile);
FileOutputStream decfos = new FileOutputStream(decfile);
Cipher encipher = Cipher.getInstance("AES");
Cipher decipher = Cipher.getInstance("AES");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecretKey skey = kgen.generateKey();
encipher.init(Cipher.ENCRYPT_MODE, skey);
CipherInputStream cis = new CipherInputStream(fis, encipher);
decipher.init(Cipher.DECRYPT_MODE, skey);
CipherOutputStream cos = new CipherOutputStream(decfos,decipher);
while((read = cis.read())!=-1)
{
fos.write((char)read);
fos.flush();
}
fos.close();
while((read=encfis.read())!=-1)
{
cos.write(read);
cos.flush();
}
cos.close();
}catch (Exception e) {
// TODO: handle exceptione
e.printStackTrace();
}
and my videoplay back code is
try {
//set the media controller in the VideoView
videoView.setMediaController(mediaControls);
mediaControls.setAnchorView(videoView);
//set the uri of the video to be played
videoView.setVideoURI(Uri.fromFile(new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/appvVideo/3.mp4")));
} catch (Exception e) {
Log.e("Error", e.getMessage());
e.printStackTrace();
}
Can anyone tell me what am i doing wrong.
what is good way for
download and encrypt the video and later decrypt form app that can be play only with app?
Related
I have created android app where i play online video from url using exoplayer2 for this i have refer this Example. it working fine but now i want to add download option and also restrict that downloaded video file from other apps(downloaded video file only open inside this app like youtube downloaded videos).
I had read documentation of Downloading media provided by exoplayer but failed to implement it. Someone please help me to fulfill above requirement. Or tell me any other solution to fulfill my requirement.
I have also try Android restricting downloaded files to app, This is working fine but not fulfill requirement(Downloaded video not showing in gallery or media store but file is present on this path Android/data/package_name/file_name) from where we easily access downloaded file from outside the app.
Thankyou in advance.
I got the solution :)
i have download video from url using Download Manager and store file on public path. This is the code
public void downloadVideo(String url) {
Uri Download_Uri = Uri.parse(url);
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
//Restrict the types of networks over which this download may proceed.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
//Set whether this download may proceed over a roaming connection.
request.setAllowedOverRoaming(false);
// Visibility of the download Notification
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
//Set the title of this download, to be displayed in notifications (if enabled).
request.setTitle("Downloading");
//Set a description of this download, to be displayed in notifications (if enabled)
request.setDescription("Downloading File");
//Set the local destination for the downloaded file to a path within the application's external files directory
/*request.setDestinationInExternalFilesDir(MainActivity.this, Environment.DIRECTORY_MOVIES, "Shivam196.mp4");*/ //For private destination
//Set the local destination for the downloaded file to a path within the application's external files directory
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MOVIES, "Shivam196.mp4"); // for public destination
DownloadManager downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
downloadID = downloadManager.enqueue(request);// enqueue puts the download request in the queue.
}
After successfully downloaded file, I have encrypt that file by passing file path on below method:
private void encryptFile(String filePath) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
int read;
FileInputStream fis = new FileInputStream(new File(filePath));
File outfile = new File(Environment.getExternalStorageDirectory() + "/" + FOLDER_NAME + "/" + "test2_enc.mp4");
if(!outfile.exists())
outfile.createNewFile();
FileOutputStream fos = new FileOutputStream(outfile);
Cipher encipher = Cipher.getInstance("AES");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
//byte key[] = {0x00,0x32,0x22,0x11,0x00,0x00,0x00,0x00,0x00,0x23,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
SecretKey skey = kgen.generateKey();
encipher.init(Cipher.ENCRYPT_MODE, skey);
CipherInputStream cis = new CipherInputStream(fis, encipher);
byte[] buffer = new byte[1024]; // buffer can read file line by line to increase speed
while((read = cis.read(buffer)) >= 0)
{
fos.write(buffer, 0, read);
fos.flush();
}
fos.close();
Toast.makeText(this, "File encrypted", Toast.LENGTH_SHORT).show();
//call method for decrypt file.
decryptFile(Environment.getExternalStorageDirectory() + "/" + FOLDER_NAME + "/" + "test_enc.mp4", skey);
}
And then decrypt the file by passing encrypted file path and secret key to below method:
private void decryptFile(String encryptFilePath, SecretKey secretKey) throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException {
int read;
File outfile = new File(encryptFilePath);
File decfile = new File(Environment.getExternalStorageDirectory() + "/" + FOLDER_NAME + "/" + "test_dec.mp4");
if(!decfile.exists())
decfile.createNewFile();
FileOutputStream decfos = new FileOutputStream(decfile);
FileInputStream encfis = new FileInputStream(outfile);
Cipher decipher = Cipher.getInstance("AES");
decipher.init(Cipher.DECRYPT_MODE, secretKey);
CipherOutputStream cos = new CipherOutputStream(decfos,decipher);
byte[] buffer = new byte[1024]; // buffer can read file line by line to increase speed
while((read=encfis.read(buffer)) >= 0)
{
cos.write(buffer, 0, read);
cos.flush();
}
cos.close();
Toast.makeText(this, "File decrypted", Toast.LENGTH_SHORT).show();
}
Note: Perform encryption and description operation on background service.
Is it possible to download a PDF from server and save in format that only my application can read?
This is my working example used in my app ....hope this help you
Is it possible to download pdf from server and save
Yes i have use retrofit library to download pdf file from server you can use Volly or Loopj AsyncTask as well
After downloading pdf file you will get InputeStream object of file than encrypt that and store in app private folder (so no other application can able to use it)
public static File encryptAndSaveFileInPrivateFolder(
Context context, String albumName, InputStream inputStream, String fullFileName) {
File file = null;
try {
// Get the directory for the app's private pictures directory.
File fileDirectory = new File(context.getExternalFilesDir(
Environment.DIRECTORY_PICTURES),""+albumName);
if (!fileDirectory.exists()) {
fileDirectory.mkdirs();
}
file = new File(fileDirectory,""+fullFileName);
if (file.exists()) {
file.delete();
}
FileOutputStream output = new FileOutputStream(file);
encrypt(inputStream,output);
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return file;
}
This method encrypt your file
public static void encrypt(InputStream fis,FileOutputStream fos ) throws IOException, NoSuchAlgorithmException
, NoSuchPaddingException, InvalidKeyException {
// Here you read the cleartext.
//FileInputStream fis = new FileInputStream("data/cleartext");
// This stream write the encrypted text. This stream will be wrapped by another stream.
// FileOutputStream fos = new FileOutputStream("data/encrypted");
String password ="passwordProtectd";
// Length is 16 byte
byte[] inputByte = password.getBytes("UTF-8");
SecretKeySpec sks = new SecretKeySpec(inputByte, "AES");
// SecretKeySpec sks = new SecretKeySpec(password.getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
}
Than show pdf using intent
public void decryptFileAndShow(Context context,File mFile) {
try{
if (null != mFile) {
String parentPath = mFile.getAbsoluteFile().getParent();//Actual encrypted file path
File tempFile = new File(parentPath, "report.pdf"); //Created new file that decrypted format after view we will delete this
//tempFile =File.createTempFile("prefix","TestMyPDF.pdf", context.getExternalFilesDir(""));
Utilities.decrypt( new FileInputStream(mFile), new FileOutputStream(tempFile));
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(tempFile), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
context.startActivity(intent);
tempFile.deleteOnExit();
}
}catch (Exception e){
e.printStackTrace();
}
}
Last the method used for decryption
public static void decrypt(FileInputStream fis,FileOutputStream fos ) throws IOException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException {
// FileInputStream fis = new FileInputStream("data/encrypted");
// FileOutputStream fos = new FileOutputStream("data/decrypted");
String password ="passwordProtectd";
byte[] inputByte = password.getBytes("UTF-8");
SecretKeySpec sks = new SecretKeySpec(inputByte, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
}
Is it possible to download pdf from server.
Yes, it is possible. Download your pdf and encrypt and decrypt your file accordingly.
You can try like this using CipherOuputStream and CipherInputStream:
byte[] buf = new byte[1024];
Encryption:
public void encrypt(InputStream in, OutputStream out) {
try {
// Bytes written to out will be encrypted
out = new CipherOutputStream(out, ecipher);
// Read in the cleartext bytes and write to out to encrypt
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
out.write(buf, 0, numRead);
}
out.close();
} catch (java.io.IOException e) {
}
}
Decryption:
public void decrypt(InputStream in, OutputStream out) {
try {
// Bytes read from in will be decrypted
in = new CipherInputStream(in, dcipher);
// Read in the decrypted bytes and write the cleartext to out
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
out.write(buf, 0, numRead);
}
out.close();
} catch (java.io.IOException e) {
}
}
If I understand your question correctly, you want your application to be the only application that reads this particular PDF files. You want to know how you can ensure that you do that.
Since your requirement is not genuine(hacky), the solution also has to be a bit hacky.
You can download the file and store it with your own custom extension (eg. file.mypdf)
Have an intent filter, that supports mimetypes matching .mypdf files
You could have the server encrypt the download and your client side app decrypt it using a public/private key pair. This would prevent anyone with a snooping proxy from observing and saving your content, but it wouldn't deter the most determined users from stealing these documents as they would eventually exist in decrypted form somewhere. To achieve that you'd probably ave to create your own PDF viewer and damage the bytes of the PDF in a way that your viewer can do, but no other viewer can recover
Hi i am creating a sample to lock file or folder in android. I have a issue when i encrypt or decrypt large size (more than 1 GB) file it takes too much time.
Please help me to encrypt and decrypt file fastly.
Here i am attaching code which i am using on below
if (!isEncrypted) {
FileInputStream fis = new FileInputStream(path);
// This stream write the encrypted text. This stream will be wrapped by another stream.
FileOutputStream fos = new FileOutputStream(path + ".abcd");
// Length is 16 byte
SecretKeySpec sks = new SecretKeySpec("abcdefghijklmnop".getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[1024];
try {
while ((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
new File(path).deleteOnExit();
isEncrypted = true;
runOnUiThread(new Runnable() {
#Override
public void run() {
btnEncrypt.setText("Decrypt Path");
deleteMyFile(path);
}
});
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
FileInputStream fis = new FileInputStream(path + ".abcd");
FileOutputStream fos = new FileOutputStream(path);
SecretKeySpec sks = new SecretKeySpec("abcdefghijklmnop".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[1024];
while ((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
isEncrypted = false;
runOnUiThread(new Runnable() {
#Override
public void run() {
deleteMyFile(path + ".abcd");
btnEncrypt.setText("Encrypt Path");
}
});
}
} catch (final Exception e) {
runOnUiThread(new Runnable() {
#Override
public void run() {
progressDialog.setMessage(e.getMessage());
}
});
I hope you found a way to do this. But, here is how I do it.
I realized that writing our own AES classes in java Or C is not recommendable way if you are especially just focused on the end result. Java is pretty slow in comparison with C, but in java you can use multithreading whereas in C you can't. Of course there are aes c programs which do a better job. But using them is difficult. You said you want to encrypt 1GB file under a minute. So, do this.
Install Userland Or Termux and install openssl. Next cd to your file storage location and try aes encrypt command. To automate it, write a bash script and run it. Openssl can easily do 23 MBps to 68 MBps.
So the scenario of my problem is in my application I am fetching some file from the internet then I put them in internal storage then when user wants to access these file User can access them through my application.
I did all the thing but I want to provide some security in my application So what I want is?
User can see my file only in my application. User unable to access them from the file manager. Don't tell me the solution to put dot
before file name or folder name I did that the problem with this
solution is when I access them by putting dot before file name the
file are again visible .
I also want that when the user open my file ,just like a pdf in pdf reader He/She restricted to save or download them through pdf
reader or another application.
Any Kind of help is appreciated by me.
You can encrypt that file so user won't be able to access them. here is the encryption method which works for me.
public void encrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
// Here you read your file.
FileInputStream fis = new FileInputStream("Path Of your file");
// This stream write the encrypted text. This stream will be wrapped by another stream.
FileOutputStream fos = new FileOutputStream("Path Of your file");
// Length is 16 byte
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
}
Here is the method for decryption of particular file.
public void decrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream("Path Of your file");
FileOutputStream fos = new FileOutputStream("Path Of your file");
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();}
you can encrypt your files with an encryption algorithm and save them with your custom file extension then you can make an intent filter for opening them from File Manager and for more security i prefer the JNI For whole Encryption system .
I am making an Android application, and I want to prevent users from opening some folder. In that folder user can store image or video files. It would be great if I could protect that folder with password.
Which is the best way to do that?
Here is Both function for encrypt and decrypt file in Sdcard folder.
we can not lock folder but we can encrypt file using AES in Android, it may help you.
static void encrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
// Here you read the cleartext.
FileInputStream fis = new FileInputStream("data/cleartext");
// This stream write the encrypted text. This stream will be wrapped by another stream.
FileOutputStream fos = new FileOutputStream("data/encrypted");
// Length is 16 byte
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
// Create cipher
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, sks);
// Wrap the output stream
CipherOutputStream cos = new CipherOutputStream(fos, cipher);
// Write bytes
int b;
byte[] d = new byte[8];
while((b = fis.read(d)) != -1) {
cos.write(d, 0, b);
}
// Flush and close streams.
cos.flush();
cos.close();
fis.close();
}
static void decrypt() throws IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
FileInputStream fis = new FileInputStream("data/encrypted");
FileOutputStream fos = new FileOutputStream("data/decrypted");
SecretKeySpec sks = new SecretKeySpec("MyDifficultPassw".getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, sks);
CipherInputStream cis = new CipherInputStream(fis, cipher);
int b;
byte[] d = new byte[8];
while((b = cis.read(d)) != -1) {
fos.write(d, 0, b);
}
fos.flush();
fos.close();
cis.close();
}
You should save this information on the internal storage. Normally other apps can't access these files. From the quideliness:
You can save files directly on the device's internal storage. By default, files saved to the internal storage are private to your application and other applications cannot access them (nor can the user). When the user uninstalls your application, these files are removed.
See the link: http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
Insted of LOCK i will saggest you make folder with . like foldername -> .test
user cant see that folder here is code
File direct = new File(Environment.getExternalStorageDirectory() + "/.test");
if(!direct.exists())
{
if(direct.mkdir())
{
//directory is created;
}
}
above code is create folder with name ".test" (in SD CARD) then save your data(file, video.. whatever) in this folder user cant access it.
if you create folder in internal storage then if user clear data of your app then that folder may EMPTY!