For downloading stuff I work with the apache classes HTTPResponse HTTPClient etc.
I check for a valid download like this:
entity.writeTo(new FileOutputStream(outfile));
if(outfile.length()!=entity.getContentLength()){
long fileLength = outfile.length();
outfile.delete();
throw new Exception("Incomplete download, "+fileLength+"/"
+entity.getContentLength()+" bytes downloaded");
}
But it seems that the exception is never triggered. How to properly handle this? Is entity.getContentLength the length of the file on server or the amount of data received?
The file request should always come with a MD5 checksum. If you have an MD5 header then all you need to do is check that against the files generated MD5. Then your done, its better to do it this way as you can have a file with the same number of bytes but one byte gets garbled in transmission.
entity.writeTo(new FileOutputStream(outfile));
String md5 = response.getHeaders("Content-MD5")[0].getValue();
byte[] b64 = Base64.decode(md5, Base64.DEFAULT);
String sB64 = IntegrityUtils.toASCII(b64, 0, b64.length);
if (outfile.exists()) {
String orgMd5 = null;
try {
orgMd5 = IntegrityUtils.getMD5Checksum(outfile);
} catch (Exception e) {
Log.d(TAG,"Exception in file hex...");
}
if (orgMd5 != null && orgMd5.equals(sB64)) {
Log.d(TAG,"MD5 is equal to files MD5");
} else {
Log.d(TAG,"MD5 does not equal files MD5");
}
}
Add this class to your project:
public class IntegrityUtils {
public static String toASCII(byte b[], int start, int length) {
StringBuffer asciiString = new StringBuffer();
for (int i = start; i < (length + start); i++) {
// exclude nulls from the ASCII representation
if (b[i] != (byte) 0x00) {
asciiString.append((char) b[i]);
}
}
return asciiString.toString();
}
public static String getMD5Checksum(File file) throws Exception {
byte[] b = createChecksum(file);
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
public static byte[] createChecksum(File file) throws Exception {
InputStream fis = new FileInputStream(file);
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
fis.close();
return complete.digest();
}
}
Related
This array of questions and answers,
R.raw.ikhlas example is the question to answer R.raw.jwbalikhlas
int[] rawQuetion = {R.raw.alfalaq, R.raw.alikhlas, R.raw.alkafirun, R.raw.allahab};
int [] rawAnswer={R.raw.jwbaliklas};
This method to randomize questions
//fisher-yates Shuffle
public void playSoal() {
shuffleArray(rawQuetion);
try{
int idx = new Random().nextInt(rawQuetion.length);
mp = MediaPlayer.create(this, rawQuetion[idx]);
mp.start();
}catch(Exception e){
Log.e("ERROR", "Media Player", e);
mp = null;
mp.release();
mp.stop();
e.printStackTrace();
}
}
static void shuffleArray(int[] arr)
{
Random rnd = new Random();
for (int i = arr.length - 1; i > 0; i--)
{
int index = rnd.nextInt(i + 1);
// Swap
int a = arr[index];
arr[index] = arr[i];
arr[i] = a;
}
}
I want when the quiz questions selected at random, will answer here
public void audioFile() throws IOException{
InputStream is = getResources().openRawResource(R.raw.jwbaliklas);//I want this to be obtained from the above array
ByteArrayOutputStream out = new ByteArrayOutputStream();
BufferedInputStream in = null;
in = new BufferedInputStream(is);
int read;
byte[] buff = new byte[1024];
while ((read = in.read(buff)) > 0)
{
out.write(buff, 0, read);
}
out.flush();
byte[] audioBytes = out.toByteArray();
for (int i = 0; i < audioBytes.length; i++) {
audioBytes[i] = (byte) ((audioBytes[i]) & 0xFF); }
absNormalizedSignal = hitungFFT(audioBytes);
AppLog.logString("===== From audio File");
}
If you pass the array id for the resource you want to open, you can use the index directly from the array of integers (as long as it is visible from the audioFile scope.
public void audioFile(#RawRes int i) throws IOException {
InputStream is = getResources().openRawResource(rawQuestion[i]);
...
}
Also, you have to change include the annotation #RawRes:
#RawRes int[] rawQuestion = {R.raw.alfalaq, R.raw.alikhlas, R.raw.alkafirun, R.raw.allahab};
#RawRes int[] rawAnswer = {R.raw.jwbaliklas};
Im trying to implement AES in an Android application. The server is a PHP server.
This is the AES code :
public class AES{
private String SecretKey = "89432hjfsd891787";
private String iv = "fedcba9876543210";
private IvParameterSpec ivspec;
private SecretKeySpec keyspec;
private Cipher cipher;
public AES()
{
ivspec = new IvParameterSpec(iv.getBytes());
keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES");
try {
cipher = Cipher.getInstance("AES/CBC/NoPadding");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public byte[] encrypt(String text) throws Exception
{
if(text == null || text.length() == 0)
throw new Exception("Empty string");
byte[] encrypted = null;
try {
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
encrypted = cipher.doFinal(padString(text).getBytes());
} catch (Exception e)
{
throw new Exception("[encrypt] " + e.getMessage());
}
return encrypted;
}
public byte[] decrypt(String code) throws Exception
{
if(code == null || code.length() == 0)
throw new Exception("Empty string");
byte[] decrypted = null;
try {
cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);
decrypted = cipher.doFinal(hexToBytes(code));
} catch (Exception e)
{
throw new Exception("[decrypt] " + e.getMessage());
}
return decrypted;
}
public static String bytesToHex(byte[] data)
{
if (data==null)
{
return null;
}
int len = data.length;
String str = "";
for (int i=0; i<len; i++) {
if ((data[i]&0xFF)<16)
str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
else
str = str + java.lang.Integer.toHexString(data[i]&0xFF);
}
return str;
}
public static byte[] hexToBytes(String str) {
if (str==null) {
return null;
} else if (str.length() < 2) {
return null;
} else {
int len = str.length() / 2;
byte[] buffer = new byte[len];
for (int i=0; i<len; i++) {
buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16);
}
return buffer;
}
}
private static String padString(String source)
{
char paddingChar = ' ';
int size = 16;
int x = source.length() % size;
int padLength = size - x;
for (int i = 0; i < padLength; i++) {
source += paddingChar;
}
return source;
}
}
I get an error while decrypting the incoming string : Cipher functions:EVP_DecryptFinal_ex:DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
How do i go about this?
Manually padding the String representation of the plaintext with spaces is not a good padding mechanism. Instead, you should use AES/CBC/PKCS5Padding which will handle the padding as prescribed in PKCS #5/#7.
You should also:
generate a unique IV per encryption operation rather than re-using the same value for all messages
Use an authenticated mode of operation (GCM, HMAC/SHA-256 MAC over cipher text, etc.)
Store the key in hexadecimal representation of the raw bytes rather than an ASCII/UTF-8 String encoding (not specified in your code)
Encode the cipher text in Base64 or Hex before serializing/transmitting. Encoding errors can contribute to padding exceptions during decryption.
I'm using this code to download from a URL ,it works great with android 4,but in the other hand it doesn't work with android 2.3. Can someone tell what have i done wrong ?
URL url = new URL(sUrl);
URLConnection connection = url.openConnection();
connection.connect();
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(pathFolder+"/"+fileName);
byte data[] = new byte[1024];
long total = 0;
int count;
while ((count = input.read(data)) != -1) {
total += count;
// publishing the progress....
publishProgress((int) (total * 100 / fileLength));
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
It works for me. Here is my method:
private boolean dowloadFile(String url, File saveFile) {
int BUFF_SIZE = 1024 * 1024; //1Mo
long length = 0;
long current = 0;
if(saveFile.exists())
current = saveFile.length();
try {
DefaultHttpClient http = new DefaultHttpClient();
HttpGet request = new HttpGet(url);
if(current>0)
request.addHeader("Range", "bytes=" + current + "-");
HttpResponse response = http.execute(request);
if (response.getStatusLine().getStatusCode() != 200 && response.getStatusLine().getStatusCode() != 206) {
return false;
}
Header[] headers = response.getHeaders("Content-Range");
if(headers.length>0) {
String s = headers[0].getValue();
length = Integer.valueOf(s.subSequence(s.indexOf("/")+1, s.length()).toString());
} else {
Header[] headers2 = response.getHeaders("Content-Length");
if(headers2.length>0)
length = Integer.valueOf(headers2[0].getValue());
if(current>0) {
saveFile.delete();
current = 0;
}
}
BufferedInputStream ls = new BufferedInputStream(response.getEntity().getContent());
long nexttime = 0;
RandomAccessFile fos = new RandomAccessFile(saveFile, "rw");
fos.seek(current);
byte[] buffer = new byte[BUFF_SIZE];
while (current < length) {
boolean buffFull = false;
int currentBuff = 0;
int readSize = 0;
while (buffFull == false) {
readSize = ls.read(buffer, currentBuff, BUFF_SIZE - currentBuff);
if (readSize == -1)
buffFull = true;
else {
currentBuff += readSize;
if (currentBuff == BUFF_SIZE)
buffFull = true;
}
}
fos.write(buffer, 0, currentBuff);
current += currentBuff;
long time = SystemClock.elapsedRealtime();
if (nexttime < time) {
// Progress
nexttime = time + 1000;
}
}
fos.close();
// Progress Finish
} catch(Exception e) {
e.printStackTrace();
return false;
}
return true;
}
I hope I have helped you !
I wrote the following code to read some data (specifically a file) received by an Android app through a socket:
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
byte[] buffX = new byte[30054];
int k = inputStream.read(buffX,0,30054);
I know that the data I am sending from a code written in C is a file with 30054 bytes.
The problem is that the variable k is less than 2000, ie, it does not read all the file that was sent or some part of the file was thrown away. I already checked that the size of the receiver buffer (in the Android app) is more than 80kB.
I tested the same code with a file of size 1662 bytes, and as I expected the variable k is equal to 1662 bytes.
What am I doing wrong? What am I missing?
Do I need to close the socket?, which is something I prefer to do when I close the app, not during the code I showed.
ANDROID APP CODE:
#SuppressLint("HandlerLeak")
public class DisplayNewActivity extends Activity {
...
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mainnewact);
mHandler = new Handler() { // used to show the number of bytes that were read
#Override
public void handleMessage(Message msg) {
int d2 = (Integer)msg.obj;
commentS.setText(Integer.toString(d2));
}
}
...
cThread = new Thread(new ClientThread()); // used to start socket connection
rThread = new Thread(new RcvThread()); // used to read incoming packages once the socket has been connected
cThread.start();
}
public class ClientThread implements Runnable {
public void run() {
try {
...
socket = new Socket(serverIpAddress, Integer.parseInt(serverPort));
rThread.start();
while (connected) { };
...
} catch (Exception e) { startActivity(intentback);}
}
}
#SuppressLint("HandlerLeak")
public class RcvThread implements Runnable {
public void run() {
while (connected) {
try {
DataInputStream inputStream = new DataInputStream(socket.getInputStream());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] imBytes = new byte[31000];
int numRead = 0;
while ((numRead = inputStream.read(imBytes)) >= 0) {
baos.write(imBytes,0,numRead);
}
byte[] imageInBytes = baos.toByteArray();
int k = imageInBytes.length;
Message msg = new Message();
msg.obj = k;
mHandler.sendMessage(msg);
} catch (Exception e) {
Log.e("SocketConnectionv02Activity", "C: ErrorRCVD", e);
}
}
}
}
}
C CODE:
...
#include <sys/sendfile.h>
...
int main(int argc, char *argv[]){
int sockfd, newsockfd, portno;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
int fdfile;
struct stat stat_buf;
off_t offset = 0;
int img2send = 1;
char buffer[256];
int closeSocket = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {error("ERROR opening socket"); exit(1);}
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 55000;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
error("ERROR on binding");
close(sockfd);
exit(1);
}
listen(sockfd,1);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0) {
error("ERROR on accept");
close(sockfd);
exit(1);
}
while (closeSocket == 0) {
if (img2send == 1) { // interchange the file that is sent through the socket
fdfile = open("/home/gachr/Desktop/CamaraTest/fig1bmp.bmp", O_RDONLY);
img2send = 2;
} else {
fdfile = open("/home/gachr/Desktop/CamaraTest/fig2bmp.bmp", O_RDONLY);
img2send = 1;
}
if (fdfile == -1) {
close(sockfd);
close(newsockfd);
exit(1);
} else {
fstat(fdfile, &stat_buf);
offset = 0;
n = sendfile(newsockfd, fdfile, &offset, stat_buf.st_size);
if (n == stat_buf.st_size) { printf("Complete transfering file\n"); }
close(fdfile);
}
sleep(5);
bzero(buffer,256);
n = recv(newsockfd,buffer,1,MSG_DONTWAIT); // to close the socket from the Android app, which is working
if (n > 0) {
if (buffer[0] == 48){ closeSocket = 1;}
}
}
close(newsockfd);
close(sockfd);
return 0;
}
It's hard to say when you are not there:)
But I would do the following:
read progressively fewer bytes at a time and build the complete
array of bytes from this smaller chunks
debug these lines and see exactly when the 'bug' appears
The read method does not read the full stream. it only reads the currently available bytes in the stream buffer.
To read the full data from stream you can either use the readFully() method or use the following code to read the full data from stream:
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] bytes = new byte[8192];
int numRead = 0;
while ((numRead = inputStream.read(bytes)) >= 0) {
baos.write(bytes,0,numRead);
}
byte[] fileData = baos.toByteArray();
So i have this code here;
myIntent.putExtra("schedule",serializableClass);
and this intent goes to my Broadcast Reciever and i did get that serializable as below,
public void onRecieve(Context context, Intent intent)
{
Schedule s = (Schedule) intent.getSerializableExtra("schedule");
}
but it always returns even though when i put the Extras its not null, even checked before passing it on myIntent.putExtra() i really don't know what happen returns, why does it always returns null?.. anyone knows this problem?
The cast is wrong, i would be more easier to pass the serialized string and do deserialization. I' m using this class.
public final class ObjectSerializer {
private ObjectSerializer() {
}
public static String serialize(Serializable obj) throws IOException {
if (obj == null)
return "";
try {
ByteArrayOutputStream serialObj = new ByteArrayOutputStream();
ObjectOutputStream objStream = new ObjectOutputStream(serialObj);
objStream.writeObject(obj);
objStream.close();
return encodeBytes(serialObj.toByteArray());
} catch (Exception e) {
throw new IOException("Serialization error: " + e.getMessage(), e);
}
}
public static Object deserialize(String str) throws IOException {
if (str == null || str.length() == 0)
return null;
try {
ByteArrayInputStream serialObj = new ByteArrayInputStream(
decodeBytes(str));
ObjectInputStream objStream = new ObjectInputStream(serialObj);
return objStream.readObject();
} catch (Exception e) {
throw new IOException("Serialization error: " + e.getMessage(), e);
}
}
public static String encodeBytes(byte[] bytes) {
StringBuffer strBuf = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
strBuf.append((char) (((bytes[i] >> 4) & 0xF) + ('a')));
strBuf.append((char) (((bytes[i]) & 0xF) + ('a')));
}
return strBuf.toString();
}
public static byte[] decodeBytes(String str) {
byte[] bytes = new byte[str.length() / 2];
for (int i = 0; i < str.length(); i += 2) {
char c = str.charAt(i);
bytes[i / 2] = (byte) ((c - 'a') << 4);
c = str.charAt(i + 1);
bytes[i / 2] += (c - 'a');
}
return bytes;
}
}
after that use like this:
String scheduleSerialization = ObjectSerializer.serialize(schedule);
myIntent.putExtra("schedule",scheduleSerialization);
the last thing to do is:
public void onRecieve(Context context, Intent intent)
{
String serial = intent.getStringExtra("schedule");
if(serial!=null)
Schedule s = (Schedule) ObjectSerializer.deserialize(serial) ;
}
Using Serializable on Android is discouraged because it is slow. If you look at the android source code you will see that
the usually break down the information into multiple keys and send them as primitive types (Integer, String, etc..)
when that can't be done, the will use a Parcelable object