how can i play video from byte in android - android

I have video in my project. and for security i encrypt the video files which is working quite well.
but problem is that the
**videoView.setVideoPath("/mnt/sdcard/intro_video.3gp");**
In this method I have to pass the file.(which is decrypted)
so I am creating decrypted file on sdcard for path of file is that possible to pass bytes (which are decrypted) directly in video view. I am using Cipher for encrypt.
Here is my code for
private void decryption()throws Exception {
// TODO Auto-generated method stub
String filePath2 = path + "en/encVideo";
String filePath3 = path + "de/decVideo";
File decfile = new File(filePath3);
if(!decfile.exists())
decfile.createNewFile();
File outfile = new File(filePath2);
int read;
FileInputStream encfis = new FileInputStream(outfile);
Cipher decipher = Cipher.getInstance("AES");
decipher.init(Cipher.DECRYPT_MODE, skey);
FileOutputStream decfos = new FileOutputStream(decfile);
CipherOutputStream cos = new CipherOutputStream(decfos,decipher);
while((read=encfis.read()) != -1)
{
cos.write(read);
cos.flush();
}
cos.close();
}

If streaming the video to a VideoView without an intermediary file to store the decrypted version is what you are looking for, then the answer is Yes you can do it. You need two main components: a streaming server such as a local http instance and CipherInputStream.

I doubt you can do it. Since you are using VideoView, it would require specific headers and tail ends that suggest which format and how it is encoded etc. If you can figure out that I still doubt it can take raw file. Your best bet would be to create random file names while saving and passing that to the player.

Related

How can I get file path on raw resources in Android Studio?

I have been using this tutorial to make some face detections on picture. The problem is when I getting the file path that used on java
String xmlFile = "E:/OpenCV/facedetect/lbpcascade_frontalface.xml";
CascadeClassifier classifier = new CascadeClassifier(xmlFile);
How can I translate on android studio. I try put my lbpcascade_frontalface.xml on raw resources. CascadeClassifier is a class that opencv library provided. The only problem is they only loaded string path (on xmlfile).
this is my code.
String pathtoRes = getRawPathAtempt2(context);
CascadeClassifier cascadeClassifier = new CascadeClassifier();
cascadeClassifier.load(pathtoRes);
I translated to some method like this.
public String getRawPathAtempt2(Context context) {
return "android.resource://" + context.getPackageName() + "/raw/" + "lbpcascade_frontalface.xml";
}
I get the asertions error by opencv that tell me the file is null. Thats mean I had been wrong when I used file path on my method. how can I get file path on raw resources? help me please I have been stuck for several days now
how can i get file path on raw resources?
You can't. There is no path. It is a file on your development machine. It is not a file on the device. Instead, it is an entry in the APK file that is your app on the device.
If your library supports an InputStream instead of a filesystem path, getResources().openRawResource() on a Context to get an InputStream on your raw resource.
This is how i solved the problem with #CommonWare Answer
i'm using input stream to get file
is = context.getResources().openRawResource(R.raw.lbpcascade_frontalface);
so make the file will be opened and i will make a point to the File class
File cascadeDir = context.getDir("cascade", Context.MODE_PRIVATE);
mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
and then i make a search to the path file using getAbsolutePath like this
cascadeClassifier.load(mCascadeFile.getAbsolutePath());
take a look at my full code
try {
is = context.getResources().openRawResource(R.raw.lbpcascade_frontalface);
File cascadeDir = context.getDir("cascade", Context.MODE_PRIVATE);
mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
os = new FileOutputStream(mCascadeFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
is.close();
os.close();
cascadeClassifier.load(mCascadeFile.getAbsolutePath());
} catch (IOException e) {
Log.i(TAG, "face cascade not found");
}
Uri video = Uri.parse("android.resource://com.test.test/raw/filename");
Using this you can access the file in raw folder, if you want to access the file in asset folder use this URL...
file:///android_asset/filename
Make sure you don't add the extension to the filename. E.g. "/movie" not "/movie.mp4".
Refer to this link:
Raw folder url path?
We can use this Alternative method for finding the path of Files in Raw Folder.
InputStream inputStreamdat=getResources().openRawResource(R.raw.face_landmark_model);
File model=getDir("model", Context.MODE_PRIVATE);
File modelFile=new
File(model,"face_landmark_model.dat");
FileOutputStream os1 = new
FileOutputStream(modelFile);
byte[] buffer1 = new byte[4096];
int bytesRead1;
while ((bytesRead1=inputStreamdat.read(buffer1))!=-1) {
os1.write(buffer1, 0, bytesRead1);
}
inputStreamdat.close();
os1.close();
You Can Use
modelFile.getAbsolutePath()); For getting the Path

Android read file from CipherInputStream without rewrite the file

Is there someone who know how to read decrypted file without rewrite it into the original file?
After downloading the file, the file automatically encrypted. When I want to open the file, the file will be decrypted first but the problem is how to read the file from CipherInputStream so that no need to convert the file back to the original.
void decrypt(File file1, String nama) throws IOException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException {
md5 hash = new md5();
String sapi = hash.md5(nama);
FileInputStream fis = new FileInputStream(file1+ "/" + sapi);
FileOutputStream fos = new FileOutputStream(file1 + "/decrypted.json");
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();
}
I can open the decrypted file but it will duplicate between encrypted and original if I use the code above.
FileOutputStream fos = new FileOutputStream(file1 + "/decrypted.json");
writes to the File object passed in as the first parameter to the decrypt method
decrypt(File file1 ...
Which is also the file object you are reading in.
So when you do fos.write(d, 0, b);you are writing back to that File object which is the same object that you are reading from.
So either write to a different file or just don't write anything out at all.
The new FileOutputStreammethod can take a file name instead of a File object as described here Relevant excerpt states
FileOutputStream (String name,
boolean append)
Creates a file output stream to write to the file with the specified
name. If the second argument is true, then bytes will be written to
the end of the file rather than the beginning. A new FileDescriptor
object is created to represent this file connection.
First, if there is a security manager, its checkWrite method is called
with name as its argument.
If the file exists but is a directory rather than a regular file, does
not exist but cannot be created, or cannot be opened for any other
reason then a FileNotFoundException is thrown.
so maybe you want FileOutputStream fos = new FileOutputStream("/decrypted.json", true|false)
setting the second parameter to either true or false depending on whether or not you want the file appended to or overwritten?
It's a little difficult to provide an exact solution to your problem as you don't clearly state what your desired result is so I have made some assumptions which may be wrong but either way the above should help you find the solution you need

Android: video saved to gallery won't play

I've got a rather odd problem. I'm writing an Android application using the Xamarin framework, and I also have an iOS version of the same app also written in Xamarin. In the app the user can send photos and videos to their friends, and their friends may be on either iOS or Android. This all works fine, and videos taken on an iPhone can be played on an Android device and vice versa.
The problem I am having is when I try to programmatically save a video to the Android gallery, then that video is not able to be played in the gallery. It does appear that the video data it's self is actually copied, but the video is somehow not playable.
My videos are encoded to the mp4 format using the H.264 codec. I believe this is fully supported in Android, and like I said the videos play just fine when played via a VideoView in the app.
The code I am using to copy the videos to the gallery is below. Does anyone have any idea what I am doing wrong here?
public static void SaveVideoToGallery(Activity activity, String filePath) {
// get filename from path
int idx = filePath.LastIndexOf("/") + 1;
String name = filePath.Substring(idx, filePath.Length - idx);
// set in/out files
File inFile = new File(filePath);
File outDir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMovies);
File outFile = new File(outDir, name);
// Make sure the Pictures directory exists.
outDir.Mkdirs();
// save the file to disc
InputStream iStream = new FileInputStream(inFile);
OutputStream oStream = new FileOutputStream(outFile);
byte[]data = new byte[iStream.Available()];
iStream.Read();
oStream.Write(data);
iStream.Close();
oStream.Close();
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.ScanFile(
activity.ApplicationContext,
new String[] { outFile.ToString() },
null,
null);
}
NOTE: I know this is all in C#, but keep in mind that all the Xamarin framework does is provide an API to the native Android methods. Everything I am using is either Java or Android backed classes/functions.
Thanks!
Your issue is in this code snippet:
byte[]data = new byte[iStream.Available()];
iStream.Read();
oStream.Write(data);
There are a few issues here:
You never read the files contents into the data buffer; iStream.Read() will only read a single byte and return it as an integer.
new byte[iStream.Available()] will only allocate the amount of data bytes that are available to be read without blocking. It isn't the full file. See the docs on the available method.
oStream.Write(data) writes out a garbage block of data as nothing is ever read into it.
The end result is the outputted video file is just a block of empty data hence why the gallery cannot use it.
Fix it reading in the data from the file stream and then writing them into the output file:
int bytes = 0;
byte[] data = new byte[1024];
while ((bytes = iStream.Read(data)) != -1)
{
oStream.Write (data, 0, bytes);
}
Full sample:
public static void SaveVideoToGallery(Activity activity, String filePath) {
// get filename from path
int idx = filePath.LastIndexOf("/") + 1;
String name = filePath.Substring(idx, filePath.Length - idx);
// set in/out files
File inFile = new File(filePath);
File outDir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryMovies);
File outFile = new File(outDir, name);
// Make sure the Pictures directory exists.
outDir.Mkdirs();
// save the file to disc
InputStream iStream = new FileInputStream(inFile);
OutputStream oStream = new FileOutputStream(outFile);
int bytes = 0;
byte[] data = new byte[1024];
while ((bytes = iStream.Read(data)) != -1)
{
oStream.Write (data, 0, bytes);
}
iStream.Close();
oStream.Close();
// Tell the media scanner about the new file so that it is
// immediately available to the user.
MediaScannerConnection.ScanFile(
activity.ApplicationContext,
new String[] { outFile.ToString() },
null,
null);
}

Android-Compressing and Decompressing Video

I am trying to compress a video in Android before uploading. I am following a code from Stack, when I try it I can see that the file is compressed (not sure that it has actually compressed) but it reduces the file size and creates a compressed file as expected but I wont be able to open the file as its content is gibberish so I try to decompress the video as I can surely know that it has been successfully compressed which in turn has lead to decompression.
My problem is that the original file size and the decompressed file size is SAME, but the file does not open and it says "Sorry, the video cannot be played".
CODE :
Compression :
public static void compressData(byte[] data) throws Exception {
OutputStream out = new FileOutputStream(new
File("/storage/emulated/0/DCIM/Camera/compressed_video.mp4"));
Log.e("Original byte length: ", String.valueOf(data.length));
Deflater d = new Deflater();
DeflaterOutputStream dout = new DeflaterOutputStream(out, d);
dout.write(data);
dout.close();
Log.i("The Compressed Byte array is ", ""+data.length);
Log.e("Compressed byte length: ",
String.valueOf(dout.toString().getBytes().length));
}
Decompression :
public static void decompress() throws Exception {
InputStream in = new FileInputStream("/storage/emulated/0/DCIM/Camera/compressed_video.mp4");
InflaterInputStream ini = new InflaterInputStream(in);
ByteArrayOutputStream bout = new ByteArrayOutputStream(1024);
int b;
while ((b = ini.read()) != -1) {
bout.write(b);
}
ini.close();
bout.close();
String s = new String(bout.toByteArray());
System.out.println(s);
File decompressed_file = new File("/storage/emulated/0/DCIM/Camera/decompressed_video.mp4");
FileOutputStream out_file = new FileOutputStream(decompressed_file);
out_file.write(bout.toByteArray());
out_file.close();
Log.i("The Decompressed Byte array is ", ""+bout.toByteArray().length);
Log.e("De-compressed byte length: ",
String.valueOf(bout.toByteArray().length));
}
From the above code, the original byte length and the decompressed byte length is same but I am not sure why the byte array does not get write to the file. I can see that the two files of compressed_video and decompressed_video is created but I cant play either. Unable to play compressed_video.mp4 is acceptable but I should be able to play the decompressed_video.mp4 which is unavailable to play. I have been sitting on this for more than 2 days so any help would be insanely appreciated. Thanks in advance guys.

How to encrypt large video files in android

I have an application in which I am using the code to decrypt the file which is already encrypted. The file location is "/mnt/sdcard/myfolder/test.mp4". The size of test.mp4 file is approx 20MB.
When I am using the following code to decrypt the encrypted files of small size, the files are successfully decrypted but when I am trying to decrypt the large video files, an exception of outOfMemoryException is occured.
Here is the code :
FileOutputStream fos = new FileOutputStream(outFilePath);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes= new byte[16];
//byte[] b= key.getBytes(Charset.forName("UTF-8"));
byte[] b= key.getBytes("UTF-8");
Log.i("b",""+b);
int len= b.length;
Log.i("len",""+len);
if (len > keyBytes.length) len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);
byte[] results = new byte[cipher.getOutputSize(abc.length)];
try
{
Log.i("output size:", ""+cipher.getOutputSize(abc.length));
***results = cipher.doFinal(abc);***
}
catch (Exception e) {
// TODO: handle exception
Log.e("EXCEPTION:", e.getMessage());
}
fos.write(results);
NOTE: byte[] abc = new byte[64]; contains the input byte array.
From your question, or at least from the code you posted, there is nothing that would couse OutOfMemoryException, especially since array abc is only 64 bytes long. But you said you get the exception when working with large files. So my inference,
Somewhere in your code (not in posted part), you are trying to read full file into any array, or trying to hold it in array. Android does impose a memory limit on application (16 MB for most devices), this limit includes the memory used for UI elements. So there is not much memory there for you to play with.
Now ideally, what you should do is to create a decrypt block, that works with streams. CipherInputStream does looks promising. And this stackoverflow thread, might be of interest if you are thinking of using CipherInputStream.

Categories

Resources