Androidx EncryptedFile - Best way to write unencrypted File to EncryptedFile - android

I have an unencrypted File that I want to write as an EncryptedFile using the androidx.security library. The example docs show reading the existing file to be encrypted into a byte array then writing that byte array to the encrypted file. I worry if the file that needs to be encrypted is very large reading the bytes into memory could cause OOM crashes on older devices. e.g:
val inputStream = FileInputStream(file)
val bytes = inputStream.readBytes()
inputStream.close()
...
encryptedFile.openFileOutput().apply {
write(bytes)
flush()
close()
}
Wouldn't opening an input stream and then using the copyTo Kotlin extension be the less memory intensive option? Or is there a better way I am overlooking?
encryptedFile.openFileOutput().apply { // opens FileOutputStream
val inputStream = FileInputStream(file)
inputStream.copyTo(this)
inputStream.close()
flush()
close()
}

Related

Printing a receipt to a file

I can print a receipt (byte[] printer format) via a thermal printer, like this :
// Print a receipt
OutputStream outputStream = mPrinterSocket.getOutputStream();
for (byte[] packet : content)
outputStream.write(packet);
outputStream.flush();
But I can not manage to save a receipt (byte[] printer format) into a file (pdf or image).
I tried :
// Save a receipt
try (OutputStream outputStream = new FileOutputStream(filePath)) {
for (byte[] packet : content) {
outputStream.write(packet);
outputStream.flush();
}
} catch (Exception exception) {
exception.printStackTrace();
}
But it returned a corrupted file, containing:
䀛琛ᬐšℝ䴑ਊℝ䴀‬੍੍ㄊ⼵㔰ㄯ‹ㄱ㈺‱†††††慔汢⁥਱䔛ਁ′潂獩潳獮†††††††††††ᬊE‱潃慣†††††††††††⸲〲ᬊE‱慆瑮⁡††††††††††⸲〲ⴊⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭⴭਭ䔛吁呏䱁†††††††††䔠剕㐠㐮ਰਊ䔛䴀牥楣‬⃠楢湥⁴ਡਊਊᴊV
Is the process to "print a byte[] to file" different from "save a byte[] to file"? For example, I use the character {0x1b, 0x45, 0x01} to put a text in bold, is this a problem? I would like to avoid reformatting everything or using an external library.
I'd wrap the FileOutputStream into a BufferedOutputStream, instead of using a plain FOS. When reading from or writing to a file it is always a good practice to use a buffer.
Also, you don't need to flush() after each packet, just outside of the loop - as in your first example. This also improves performance.
You can use the itext library for android to create PDF file and save it. For more details Read Here

REST Server for uploading and downloading documents

I wrote an android application that part of it is to handle upload and download documents. Currently I am using the Microsoft Azure server to save the files on.
The way I am currently doing it is by turning the files to a string and saving it that way on the Azure server:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileInputStream fis;
try {
fis = new FileInputStream(new File(Uridata.getPath()));
byte[] buf = new byte[1024];
int n;
while (-1 != (n = fis.read(buf)))
baos.write(buf, 0, n);
} catch (Exception e) {
e.printStackTrace();
}
byte[] bbytes = baos.toByteArray();
item.setStringFile(Base64.encodeToString(bbytes, Base64.URL_SAFE));
item.setName(Uridata.getLastPathSegment());
where item is my class that saves the string representation and the name of the file and is being loaded to the Azure, Uridata is an Uri instance of the file chosen.
I have one main problem with this solution and it is the limit on the file size.
I am searching for a good server to use instead of the Azure (maybe a RESET one) and if there is a better way to save files of all kinds (pdf, word...).
I will also want in the future to use the same data in a web interface
Does anybody have any suggestions on how to do it?
Thanks in advance!
To start, you don't have to transform the file into a string, you can just save it as a file. You have the possibility of losing data by continuing to do that. See: How do I save a stream to a file in C#?
If you're looking for another service to save files, then you should look into Azure Blob Storage. It will allow you to upload as much data as you want to a storage service for arbitrary files. See for example:
https://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-how-to-use-blobs/

Is it possible to access a runtime decrypted file in android?

I want to decrypt a file stored at my app's res folder. This file is distributed with the app, and I'm trying to decrypt it only once during app start.
So far, I've found some answers (this one, for instance) about how to write the decrypted file into sdcard, but won't that file be available to malicious access at the sdcard?
I wish I could write the CipherInputStream into a java.io.InputStream, so I could use it without writing any decrypted data to disk. Is it possible?
I think you want something like this
private InputStream getDecodedInputStream (InputStream eis) {
Cipher cipher = Cipher.getInstance("your cipher definition");
cipher.init(Cipher.DECRYPT_MODE, "your keySpec", new IvParameterSpec("your IV parameter spec"));
InputStream decryptedInputStream = new CipherInputStream(is, cipher);
return decryptedInputStream;
}
where eis is your encrypted input stream

Reading RAW resources and saving into Internal storage

I am trying to create internal storage folder(s) and copy over my RAW files to those folder. I have following method
EDIT
private byte[] buffer = null;
private String DIR_NAME = "images/sample_images";
public void storeRAWFilesToInternalStorage()
{
buffer = new byte[3000000];
mFilesDir = tempContext.getFilesDir();
mImagesDir = new File(mFilesDir, DIR_NAME);
if (!mImagesDir.exists() && !mImagesDir.isDirectory()) dirCreated = mImagesDir.mkdirs();
InputStream fileStream = tempContext.getResources().openRawResource(R.raw.desert);
fileStream.read(buffer);
fileWithinMyDir = new File(mImagesDir, "my_sample_image.jpg");
FileOutputStream outputStream = new FileOutputStream(fileWithinMyDir);
outputStream.write(buffer);
outputStream.close();
}
it works fine, however I have following questions.
What is the buffer size should I assign since I dont know the bytes size of each file. If I assign more than required then I am wasting memory. If I am assigning less than required then image wont be saved properly.
Also, I see the image saved in my Internal Storage (using ES Fileexplorer to view files), but when I try to open it, it doesnt show up. Weird.
END EDIT
Also what if I have 100 RAW files which I would like to copy to my Internal Folder, say "images". I dont want to type following thousand of times.
InputStream fileStream = tempContext.getResources().openRawResource(R.raw.**asset_name**);
Is there a way to loop through all raw resources, read them and store them to Internal Storage folder? Can I see some code snippet?

Program crashes on trying to open a file

My android program crashes on this line when the file size is very large. Is there any way I can prevent the program from crashing ?
byte[] myByteArray = new byte[(int)mFile.length()];
Additional details :-
I am trying to send a file to server.
error log-
E/dalvikvm-heap(29811): Out of memory on a 136309996-byte allocation.
You should use a stream when reading the file. Since you've mentioned sending to a server, you should stream that file to the server.
As others have mentioned, you should consider your data size (1GB seems excessive). I haven't tested this, but the basic approach in code would look something like:
// open a stream to the file
FileInputStream fileInputStream = new FileInputStream(filePath);
// open a stream to the server
HttpURLConnection connection = new URL(url).openConnection();
DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream());
byte[] buffer = new byte[BUFFER_SIZE]; // pick some buffer size
int bytesRead = 0;
// continually read from the file into the buffer and immediately write that to output stream
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
outputStream.write(buffer);
}
Hope that is clear enough for you to fit to your needs.
Yep. Don't try to read the whole file into memory at once...
If you really need the whole file in memory you might have more luck with allocating dynamic memory for each line and storing the lines in a list. (you might be able to get a bunch of smaller chunks of memory but not one big piece)
Without knowing the context we can't tell, but normally you would parse the file into data structs rather than just storing the whole file in memory.
In JDK 7 you can use Files.readAllBytes(Path).
Example:
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.Path;
Path path = Paths.get("path/to/file");
byte[] myByteArray = Files.readAllBytes(path);
Don't try reading the complete file into memory. Instead open a stream and process the file line by line (is it's a text file) or in parts. How that has to be done depends on the problem you are trying to solve.
EDIT: You say you want to upload a file, so please check this question. You don't need to have the complete file in memory.

Categories

Resources