Hi I am getting the following exception, when decrypting a file on Android based on user supplied password:
Caused by: java.lang.ArrayIndexOutOfBoundsException: src.length=1024 srcPos=1008 dst.length=16 dstPos=16 length=16
at java.lang.System.arraycopy(Native Method)
at com.android.org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher.processBytes(PaddedBufferedBlockCipher.java:221)
at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher$BufferedGenericBlockCipher.processBytes(BaseBlockCipher.java:882)
at com.android.org.bouncycastle.jcajce.provider.symmetric.util.BaseBlockCipher.engineUpdate(BaseBlockCipher.java:674)
at javax.crypto.Cipher.update(Cipher.java:893)
at javax.crypto.CipherOutputStream.write(CipherOutputStream.java:95)
It happens randomly and from the crash reports on Google Play Store only on Android 4+. It used to work on older versions.
My Crypto wrapper:
private static final String KEY_FACTORY_ALGORITHM = "PBEWITHSHAAND128BITAES-CBC-BC";
private static final String KEY_ALGORITHM = "AES";
private static final String CIPHER_PROVIDER = "AES";
public Crypto(String password, byte[] salt) {
if (TextUtils.isEmpty(password)) {
throw new IllegalArgumentException(
"password cannot be null or empty.");
}
PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, 20,
128);
SecretKeyFactory factory;
try {
factory = SecretKeyFactory.getInstance(KEY_FACTORY_ALGORITHM);
PBEKey key = (PBEKey) factory.generateSecret(keySpec);
this.createKeyAndCipher(key.getEncoded());
} catch (Exception e) {
Log.e(this.getClass().getName(), Log.getStackTraceString(e));
throw new RuntimeException(e);
}
}
private void createKeyAndCipher(byte[] keyData)
throws NoSuchAlgorithmException, NoSuchPaddingException {
_secretKey = new SecretKeySpec(keyData, KEY_ALGORITHM);
_cipher = Cipher.getInstance(CIPHER_PROVIDER);
}
And the function that does decryption:
public void decrypt(InputStream input, OutputStream output)
throws Throwable {
_cipher.init(Cipher.DECRYPT_MODE, _secretKey);
this.encryptDecrypt(input, output);
}
public void encryptDecrypt(InputStream input, OutputStream output) throws Throwable {
final int BUFFER_SIZE = 1024;
CipherOutputStream cipherStream = new CipherOutputStream(output,
_cipher);
byte[] buffer = new byte[BUFFER_SIZE];
int count = -1;
while ((count = input.read(buffer)) != -1) {
cipherStream.write(buffer, 0, count);
}
input.close();
cipherStream.close();
}
Did something change in Android 4 version of Boucycastle?
Any hints greatly appreciated.
Thank you.
UPDATE:
Changed the code to this:
public void encryptDecrypt(InputStream input, OutputStream output) {
final int BUFFER_SIZE = 1024;
try {
byte[] buffer = new byte[BUFFER_SIZE];
int count = -1;
while ((count = input.read(buffer)) != -1) {
byte[] result = null;
if (count == BUFFER_SIZE) {
result = _cipher.update(buffer, 0, count);
} else {
result = _cipher.doFinal(buffer, 0, count);
}
if (result != null) {
output.write(result);
}
}
input.close();
output.close();
} catch (Exception e) {
Log.e(this.getClass().getName(), Log.getStackTraceString(e));
throw new RuntimeException(e);
}
}
Now I'm getting
javax.crypto.BadPaddingException: pad block corrupted
One thing should be noted: This ONLY happens when I try to decrypt the file. Short byte[] from sqlite decrypted by _cipher.doFinal(arra) works fine with the same key.
Also, in the original error at the beginning of the post,
dst.length=16 dstPos=16 length=16
I have read something somewhere about AES and data being shorter then 16.
Related
I am encrypting my videos using this link and store it in my application folder. But for large videos say, 2GB, it takes much time to decrypt and then play. so user has to wait for 1.5-2 minutes to decrypt selected video and then play it.
For that, I searched for offline video streaming. And I found this. I have same scenario but instead of downloading, I am encrypting videos from gallery. and I have used different encryption alogithm.
When I tried above link, my connection is lost everytime it goes in while loop. In catch, I get Connection is reset error. Also I didn't get some variables there. like, total, readbyte and pos variables. can anybody please explain?
I really want to decrypt and play videos at the same time. so user experience will be good.
Thank you.
EDIT
Here is my sample code :
using Android.App;
using Android.Widget;
using Android.OS;
using Android.Support.V7.App;
using Java.IO;
using Javax.Crypto;
using Javax.Crypto.Spec;
using System;
using System.IO;
using Java.Net;
using System.Threading.Tasks;
namespace SecretCalc
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme",
MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
VideoView video;
Button encrypt, decrypt;
private string sKey = "0123456789abcdef";//key,
private string ivParameter = "1020304050607080";
string path = "/sdcard/Download/";
string destpath = "/sdcard/test/";
string filename = "video1.mp4";
Stream outputStream;
string date = "20180922153533.mp4"; // Already Encrypted File Name
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
video = FindViewById<VideoView>(Resource.Id.videoView);
encrypt = FindViewById<Button>(Resource.Id.btnEncrypt);
decrypt = FindViewById<Button>(Resource.Id.btnDecrypt);
encrypt.Click += Encrypt_Click;
decrypt.Click += Decrypt_ClickAsync;
}
private async void Decrypt_ClickAsync(object sender, EventArgs e)
{
video.SetVideoPath("http://0.0.0.0:9990/");
video.Prepared += Video_Prepared;
await Task.Run(() =>
{
try
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.Bind(new InetSocketAddress("0.0.0.0", 9990));
// this is a blocking call, control will be blocked until client sends the request
Socket finalAccept = serverSocket.Accept();
outputStream = finalAccept.OutputStream;
}
catch (Exception ex)
{
}
});
await Task.Run(() => DecryptThroughSocket());
}
private void Video_Prepared(object sender, EventArgs e)
{
video.Start();
}
private bool DecryptThroughSocket()
{
try
{
byte[] raw = System.Text.Encoding.Default.GetBytes(sKey);
byte[] iv = System.Text.Encoding.Default.GetBytes(ivParameter);
int count = 0, pos = 0, total = 0, readbyte;
byte[] data = new byte[1024 * 1024];
readbyte = data.Length;
long lenghtOfFile = new Java.IO.File(Path.Combine(path, date)).Length();
FileInputStream inputStream = new FileInputStream(Path.Combine(destpath, date));
while ((count = inputStream.Read(data, 0, readbyte)) != -1)
{
if (count < readbyte)
{
if ((lenghtOfFile - total) > readbyte)
{
while (true)
{
int seccount = inputStream.Read(data, pos, (readbyte - pos));
pos = pos + seccount;
if (pos == readbyte)
{
break;
}
}
}
}
// encrypt data read before writing to output stream
byte[] decryptedData = decryptFun(raw, iv, data);
outputStream.Write(decryptedData,0,decryptedData.Length);
}
}
catch (Exception ex)
{
return false;
}
return true;
}
private void Encrypt_Click(object sender, EventArgs e)
{
try
{
FileInputStream inputStream = new FileInputStream(System.IO.Path.Combine(path, filename));
date = DateTime.Now.ToString("yyyyMMddHHmmss") + ".mp4";
DirectoryInfo dir = new DirectoryInfo(destpath);
if (!dir.Exists)
{
Directory.CreateDirectory(destpath);
}
FileOutputStream outputStream = new FileOutputStream(System.IO.Path.Combine(destpath, date));
byte[] raw = System.Text.Encoding.Default.GetBytes(sKey);
byte[] iv = System.Text.Encoding.Default.GetBytes(ivParameter);
int count = 0, pos = 0, total = 0, readbyte;
byte[] data = new byte[1024 * 1024];
readbyte = data.Length;
long lenghtOfFile = new Java.IO.File(Path.Combine(path, filename)).Length();
while ((count = inputStream.Read(data, 0, readbyte)) != -1)
{
if (count < readbyte)
{
if ((lenghtOfFile - total) > readbyte)
{
while (true)
{
int seccount = inputStream.Read(data, pos, (readbyte - pos));
pos = pos + seccount;
if (pos == readbyte)
{
break;
}
}
}
}
total += count;
// encrypt data read before writing to output stream
byte[] encryptedData = encryptFun(raw, iv, data);
outputStream.Write(encryptedData);
}
}
catch (Exception ex)
{
}
}
public static byte[] encryptFun(byte[] key, byte[] iv, byte[] clear)
{
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.GetInstance("AES/CTR/NoPadding");
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.Init(CipherMode.EncryptMode, skeySpec, ivspec);
byte[] encrypted = cipher.DoFinal(clear);
return encrypted;
}
public static byte[] decryptFun(byte[] key, byte[] iv, byte[] encrypted)
{
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.GetInstance("AES/CTR/NoPadding");
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.Init(CipherMode.DecryptMode, skeySpec, ivspec);
byte[] decrypted = cipher.DoFinal(encrypted);
return decrypted;
}
}
}
I'm retrieving a PDF in the form of a byte array from the internet. Once I recieve it, I've been able to convert it to a File using this method:
File dir = Environment.getExternalStorageDirectory();
File assist = new File(Environment.getExternalStorageDirectory() + "/Sample.pdf");
try {
InputStream fis = new FileInputStream(assist);
long length = assist.length();
if (length > Integer.MAX_VALUE) {
Log.e("Print error", "Too large");
}
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length && (numRead = fis.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
return new File(dir, "mydemo.pdf");
} catch (IOException e) {
e.printStackTrace();
return null;
}
Now that I have the file, what do I do? On the official dev site: https://developer.android.com/training/printing/custom-docs.html it doesn't give specific information for this, doesn't the Print Manager have a method to handle this for us when I give it a File? Or do I have to manually create an adapter? If so, how would I get the page count (which I read is obligatory) and what would I do in onWrite()?
This works for me to print it directly from its URL
PrintDocumentAdapter pda = new PrintDocumentAdapter() {
#Override
public void onWrite(PageRange[] pages, final ParcelFileDescriptor destination, CancellationSignal cancellationSignal, final WriteResultCallback callback) {
!!THIS MUST BE RUN ASYNC!!
InputStream input = null;
OutputStream output = null;
try {
input = new URL(YOUR URL HERE).openStream();
output = new FileOutputStream(destination.getFileDescriptor());
byte[] buf = new byte[1024];
int bytesRead;
while ((bytesRead = input.read(buf)) > 0) {
output.write(buf, 0, bytesRead);
}
callback.onWriteFinished(new PageRange[]{PageRange.ALL_PAGES});
} catch (FileNotFoundException ee) {
//TODO Handle Exception
} catch (Exception e) {
//TODO Handle Exception
} finally {
try {
input.close();
output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal, LayoutResultCallback callback, Bundle extras) {
if (cancellationSignal.isCanceled()) {
callback.onLayoutCancelled();
return;
}
PrintDocumentInfo pdi = new PrintDocumentInfo.Builder("NAME OF DOCUMENT").setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT).build();
callback.onLayoutFinished(pdi, true);
}
};
PrintManager printManager = (PrintManager) this.getSystemService(Context.PRINT_SERVICE);
printManager.print("JOB NAME", pda, null);
I am trying to encrypt and then decrypt audio file . Everything goes right but when I try to decrypt the encrypted audio , everytime I got this exception
javax.crypto.BadPaddingException: pad block corrupted
My MainActivity is like this: I want to decrypt and play the song side by side
public class MainActivity extends Activity{
private final String KEY = "abc";
Button btn_Dec, btn_In;
byte[] incrept;
byte[] decrpt;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ctx = this;
btn_Dec = (Button) findViewById(R.id.button2);
btn_In = (Button) findViewById(R.id.button1);
btn_Dec.setOnClickListener(btnDecListner);
btn_In.setOnClickListener(btnInListner);
}
public OnClickListener btnDecListner = new OnClickListener() {
public void onClick(View v) {
VincentFileCrypto simpleCrypto = new VincentFileCrypto();
try {
// decrypt the file here first argument is key and second is encrypted file which we get from SD card.
decrpt = simpleCrypto.decrypt(KEY, getAudioFileFromSdCard());
//play decrypted audio file.
playMp3(decrpt);
} catch (Exception e) {
e.printStackTrace();
}
}
};
Context ctx;
public OnClickListener btnInListner = new OnClickListener() {
public void onClick(View v) {
VincentFileCrypto simpleCrypto = new VincentFileCrypto();
try {
// encrypt audio file send as second argument and corresponding key in first argument.
incrept = simpleCrypto.encrypt(KEY, getAudioFile());
//Store encrypted file in SD card of your mobile with name vincent.mp3.
FileOutputStream fos = new FileOutputStream(new File("/sdcard/vincent.mp3"));
fos.write(incrept);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
};
/**
* #return byte array for encryption.
* #throws FileNotFoundException
*/
public byte[] getAudioFile() throws FileNotFoundException
{
byte[] audio_data = null;
byte[] inarry = null;
AssetManager am = ctx.getAssets();
try {
InputStream is = am.open("Sleep Away.mp3"); // use recorded file instead of getting file from assets folder.
int length = is.available();
audio_data = new byte[length];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
while ((bytesRead = is.read(audio_data)) != -1)
{
output.write(audio_data, 0, bytesRead);
}
inarry = output.toByteArray();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return inarry;
}
/**
* This method fetch encrypted file which is save in sd card and convert it in byte array after that this file will be decrept.
*
* #return byte array of encrypted data for decription.
* #throws FileNotFoundException
*/
public byte[] getAudioFileFromSdCard() throws FileNotFoundException
{
byte[] inarry = null;
try {
//getting root path where encrypted file is stored.
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard, "vincent.mp3"); //Creating file object
//Convert file into array of bytes.
FileInputStream fileInputStream = null;
byte[] bFile = new byte[(int) file.length()];
fileInputStream = new FileInputStream(file);
fileInputStream.read(bFile);
fileInputStream.close();
inarry = bFile;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return inarry;
}
/**
* This Method is used to play audio file after decrepting.
*
* #param mp3SoundByteArray : This is our audio file which will be play and it converted in byte array.
*/
private void playMp3(byte[] mp3SoundByteArray) {
try {
// create temp file that will hold byte array
File tempMp3 = File.createTempFile("kurchina", "mp3", getCacheDir());
tempMp3.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tempMp3);
fos.write(mp3SoundByteArray);
fos.close();
// Tried reusing instance of media player
// but that resulted in system crashes...
MediaPlayer mediaPlayer = new MediaPlayer();
FileInputStream fis = new FileInputStream(tempMp3);
mediaPlayer.setDataSource(fis.getFD());
mediaPlayer.prepareAsync();
mediaPlayer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
The encryption and decryption methods are mentioned in this class
public class VincentFileCrypto {
public byte[] encrypt(String seed, byte[] cleartext) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] result = encrypt(rawKey, cleartext);
// return toHex(result);
return result;
}
public byte[] decrypt(String seed, byte[] encrypted) throws Exception {
byte[] rawKey = getRawKey(seed.getBytes());
byte[] enc = encrypted;
byte[] result = decrypt(rawKey, enc);
return result;
}
//done
private byte[] getRawKey(byte[] seed) throws Exception {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);
kgen.init(128, sr); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
return raw;
}
private byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
private byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
}
After days of research and hard work I found the solution ,may help and save somebody's else time . Here is my answer. I changed the above code logic like this
now what is happening , I am able to successfully encrypt the file and save it in the sdcard and then decrypt it to play . No body else can play the audio.
here we go : happy coding
public class Main2Activity extends AppCompatActivity {
private String encryptedFileName = "encrypted_Audio.mp3";
private static String algorithm = "AES";
static SecretKey yourKey = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
//saveFile("Hello From CoderzHeaven asaksjalksjals");
try {
saveFile(getAudioFile());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
decodeFile();
}
public static SecretKey generateKey(char[] passphraseOrPin, byte[] salt) throws NoSuchAlgorithmException, InvalidKeySpecException {
// Number of PBKDF2 hardening rounds to use. Larger values increase
// computation time. You should select a value that causes computation
// to take >100ms.
final int iterations = 1000;
// Generate a 256-bit key
final int outputKeyLength = 256;
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec keySpec = new PBEKeySpec(passphraseOrPin, salt, iterations, outputKeyLength);
SecretKey secretKey = secretKeyFactory.generateSecret(keySpec);
return secretKey;
}
public static SecretKey generateKey() throws NoSuchAlgorithmException {
// Generate a 256-bit key
final int outputKeyLength = 256;
SecureRandom secureRandom = new SecureRandom();
// Do *not* seed secureRandom! Automatically seeded from system entropy.
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(outputKeyLength, secureRandom);
yourKey = keyGenerator.generateKey();
return yourKey;
}
public static byte[] encodeFile(SecretKey yourKey, byte[] fileData)
throws Exception {
byte[] encrypted = null;
byte[] data = yourKey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(data, 0, data.length, algorithm);
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(
new byte[cipher.getBlockSize()]));
encrypted = cipher.doFinal(fileData);
return encrypted;
}
public static byte[] decodeFile(SecretKey yourKey, byte[] fileData)
throws Exception {
byte[] decrypted = null;
Cipher cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, yourKey, new IvParameterSpec(new byte[cipher.getBlockSize()]));
decrypted = cipher.doFinal(fileData);
return decrypted;
}
void saveFile(byte[] stringToSave) {
try {
File file = new File(Environment.getExternalStorageDirectory() + File.separator, encryptedFileName);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
yourKey = generateKey();
byte[] filesBytes = encodeFile(yourKey, stringToSave);
bos.write(filesBytes);
bos.flush();
bos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
void decodeFile() {
try {
byte[] decodedData = decodeFile(yourKey, readFile());
// String str = new String(decodedData);
//System.out.println("DECODED FILE CONTENTS : " + str);
playMp3(decodedData);
} catch (Exception e) {
e.printStackTrace();
}
}
public byte[] readFile() {
byte[] contents = null;
File file = new File(Environment.getExternalStorageDirectory()
+ File.separator, encryptedFileName);
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;
}
public byte[] getAudioFile() throws FileNotFoundException
{
byte[] audio_data = null;
byte[] inarry = null;
AssetManager am = getAssets();
try {
InputStream is = am.open("Sleep Away.mp3"); // use recorded file instead of getting file from assets folder.
int length = is.available();
audio_data = new byte[length];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
while ((bytesRead = is.read(audio_data)) != -1) {
output.write(audio_data, 0, bytesRead);
}
inarry = output.toByteArray();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return inarry;
}
private void playMp3(byte[] mp3SoundByteArray) {
try {
// create temp file that will hold byte array
File tempMp3 = File.createTempFile("kurchina", "mp3", getCacheDir());
tempMp3.deleteOnExit();
FileOutputStream fos = new FileOutputStream(tempMp3);
fos.write(mp3SoundByteArray);
fos.close();
// Tried reusing instance of media player
// but that resulted in system crashes...
MediaPlayer mediaPlayer = new MediaPlayer();
FileInputStream fis = new FileInputStream(tempMp3);
mediaPlayer.setDataSource(fis.getFD());
mediaPlayer.prepare();
mediaPlayer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
I'm new at android development and I'm creating simple bluetooth app that can receive xml file and save xml file values to database. But how can I receive xml file from bytes array? Is it possible? After searchinf I found this question and based ont that question I try to save byte array to file. But how I need to test it? I can't find my file in my phone.
case Constants.MESSAGE_READ:
byte[] readBuffer = (byte[]) msg.obj;
try {
String path = activity.getFilesDir() + "/myFile.xml";
Log.d("MuTestClass", path);
FileOutputStream stream = new FileOutputStream(path);
stream.write(readBuffer);
stream.close();
} catch (Exception e1) {
e1.printStackTrace();
}
break;
You can use:
class Utils{
public static InputStream openFile(String filename) throws IOException{
AssetManager assManager = getApplicationContext().getAssets();
InputStream is = null;
is = assManager.open(filename);
return new BufferedInputStream(is);
}
public static byte[] readBytes(InputStream inputStream) throws IOException {
ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
int bufferSize = 1024;
byte[] buffer = new byte[bufferSize];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
byteBuffer.write(buffer, 0, len);
}
return byteBuffer.toByteArray();
}
}
like this:
try {
Utils.readBytes(Utils.openFile("something.xml"));
} catch (IOException e) {
e.printStackTrace();
}
I want to do an app that can edit a file, like open a txt file, edit it, save and bearing in mind its permissions. How I can do this in a activity?
Thank you.
You can create it like this:
try {
final FileOutputStream fos = openFileOutput(fileName + extension, Context.MODE_PRIVATE);
fos.close();
} catch (FileNotFoundException e) {
Log.d(TAG, "File not found: " + e.getMessage());
} catch (IOException e) {
Log.d(TAG, "Error accessing file: " + e.getMessage());
}
Next, you can open and edit it using FileInputStream.
The permissions you need to add:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
See that post or read this tutorial
Hope it´s useful
A few days later I have the next methods.
private static byte[] readFromFile(String filePath, int position, int size)
throws IOException {
RandomAccessFile file = new RandomAccessFile(filePath, "r");
file.seek(position);
byte[] bytes = new byte[size];
file.read(bytes);
file.close();
return bytes;
}
private void CopyFromAssetsToStorage(Context Context, String SourceFile, String DestinationFile) throws IOException {
InputStream IS = Context.getAssets().open(SourceFile);
OutputStream OS = new FileOutputStream(DestinationFile);
CopyStream(IS, OS);
OS.flush();
OS.close();
IS.close();
}
private void CopyStream(InputStream Input, OutputStream Output) throws IOException {
byte[] buffer = new byte[5120];
int length = Input.read(buffer);
while (length > 0) {
Output.write(buffer, 0, length);
length = Input.read(buffer);
}
}
private static void writeToFile(String filePath, String data, int position) throws IOException {
RandomAccessFile file = new RandomAccessFile(filePath, "rw");
file.seek(position);
file.write(data.getBytes());
file.close();
public static String readFileAsString(String filePath) throws IOException
{
String separator = System.getProperty("line.separator");
BufferedReader reader = new BufferedReader(new FileReader(filePath));
String line, results = "";
while( ( line = reader.readLine() ) != null)
{
results += line + separator;
}
reader.close();
return results;
}
Which, I'm using today. I hope this can help someone else.
See you soon.