Methods for multiple file upload in android - android

I have scenario where i need to transfer one or more file depending on situation over the network. The size of the files will be between 700KB and 900KB. After upload completes the server will respond with one number, irrespective of the number of files uploaded.
I have been trying to upload it with ksoap2 library after converting it to Base64, but it failed. It would fail when size of my soap header xml size goes around some where 1048000 or so chars.
Then i decided to change my way of upload and am looking to use either HttpURLConnection or http client.
I cannot decide on which one will be efficient for my scenario.
Thanks
Here is the code
code:
InputStream is = getResources()
.openRawResource(R.raw.file_name);
int size = 0;
// Read the entire resource into a local byte buffer.
byte[] buffer = new byte[1024];
try {
while ((size = is.read(buffer, 0, 1024)) >= 0) {
baos.write(buffer, 0, size);
}
is.close();
buffer = baos.toByteArray();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
base64string = new String(Base64.encode(buffer, Base64.DEFAULT));
error
org.xmlpull.v1.XmlPullParserException: unexpected type (position:END_DOCUMENT null#1:1 in java.io.InputStreamReader#4101ce48)
at org.kxml2.io.KXmlParser.nextTag(KXmlParser.java:2035)
at org.ksoap2.SoapEnvelope.parse(SoapEnvelope.java:126)
at org.ksoap2.transport.Transport.parseResponse(Transport.java:63)
at org.ksoap2.transport.HttpTransportSE.call(HttpTransportSE.java:100)

I dont know what kind of server you would like to use.
Your issue of that the files stops while upload might be in your server settings. in your php config for example you can define maximum uploaded file sizes etc.
here a php example:
public void uploadFile(){
try {
FileInputStream fis =this.openFileInput(NAME_OF_FILE);
HttpFileUploader htfu = new HttpFileUploader("http://11.0.6.23/test2.php","noparamshere", NAME_OF_FILE);
htfu.doStart(fis);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Read more: http://getablogger.blogspot.com/2008/01/android-how-to-post-file-to-php-server.html#ixzz27YPjwX8B
EDIT: You could also try to make your soap transfer more efficient by implementing MTOM:
Check out MTOM, a W3C standard designed to transfer binary files through SOAP.
From Wikipedia:
MTOM provides a way to send the binary data in its original binary form,
avoiding any increase in size due to encoding it in text.
Related resources:
SOAP Message Transmission Optimization Mechanism http://www.w3.org/TR/soap12-mtom/
Message Transmission Optimization Mechanism (Wikipedia) http://en.wikipedia.org/wiki/MTOM

Related

Google Cloud Endpoint send Image Base 64

I would like to send, from my android app to my backend API an image.
So in my android app I convert an image in base64 string. That part works perfectly.
Android Code:
Bitmap resized = Bitmap.createScaledBitmap(AccueilActivity.photo, 720, 1280, true);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
resized.compress(Bitmap.CompressFormat.JPEG, 100, baos);
byte[] byteArray = baos.toByteArray();
String encodedImage = new String(""+Base64.encodeBase64URLSafeString(byteArray));
When I want to execute the endpoint https request, it fails !
Campagneendpoint endpoint = endpointBuilder.build();
try {
result=endpoint.sendCampagne(encodedImage).execute();
} catch (IOException e) {
e.printStackTrace();
}
And I've got this error:
javax.net.ssl.SSLException: Write error: ssl=0x78edde30: I/O error during system call, Broken pipe
But If I pass directly the base64 string, It works !
Campagneendpoint endpoint = endpointBuilder.build();
try {
result=endpoint.sendCampagne("_9j_4AAQSkZJRgABAQAAAQABAAD_2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH_2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH_wAARCAUAAtADASIAAhEBAxEB_8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL_8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4-Tl5ufo6erx8vP09fb3-Pn6_8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL_8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3-Pn6_9oADAMBAAIRAxEAPwD7T-H1zNcRW0NpvF0zqpvXk82MwyLKr-UgVSXMEyw3BlMkhCq-Y44pJH7Txd4Tu4bRdVtVl1N7iF40aCQYgt_OvZGRWWMpGRK0kYVBvkljJkUHyWHg3wg8TSTQWxt0WM2U7uk0il7e4tWjCuggMk8yPiCViC3kidBBlJFct91x3WneINKYsomQovlxRlcRCTLGZ4x5ojcTqjBAsZYusJZ1QAfnUI06cIwpSVOnSknTkoq6UW-Rxh765oLVuTdnJNas-RxEJNyvCpFJLWblf4oy97eSXu2Xk4t6uz_I342eEtUudO1po1NjBGtrLN5ywYe5jurowRZVCxdFhjnk3xMy3E8UyTGNXU_k18WvCbz3275PtkkTgzi6hnilF3byyxWcqSCCW3L3MG-aR1EU90EluAYhPLH_AES_GTwULbS9Xu7GKGeyng3GWSLzpo51WWa5TUY4C2-OFseVOQA6oYfLicxu34wftAeBRosZlKQPbahNFMkzXICxSrNMsivHOyTKZpoJI7d2SNJRvVAPLuBXq4erSjVV6rqSlCKmqkpNpuaa5E37t7cya15rSam1d5WurTUZW5XrHtfmTV73fNayV3zK8rJ2_Inxb4ZtLiW50zUrOUveK8dndrPHBAPneG7uZrbdPdNDLaRyeQ7TqFuxbcOZnQeUahZySTQLcSRS3NmstirQSQtYtFZPLIksMEyl47d5CZXkuIVEs0zyxqsgdj9P-LNHihubyK7R2NpdbEVlElvc2NwUe3uoyCJIp7O4ZIJleQvL56vaxiJLgx_PfibTLa1ubu7MiyWsCMbYRxg_ZgDM0VtvkuPuPO8kSSrEVXzY4gGIGfTpSao8sVJ35W73jyxlKUownZtXSvyt2k21z1JO0X106UJJyvBpWWkVJNQbjH3bJ2WrXK9XJp3cVJ-fXVmdUs7mV4AtoqmSTyobiezUokcVpdTpIZhbqtyBNPZLGsUjG5UShVmu2yDZaXLA_ny75fMtljdoCG8uPe0kkTFZVlaHdJL5G6QohuXZsb_O0bh7v7DPYQKLZ5_s5vHRZoil1Yz3qW21YkRDafZ47GYTTboh9pMZWOIPGufO3mRrJOp82MM1u0TxRp5DbwsEcZWZSu4Mkc-VmjV549pWOUN0RqyTdk4q0XHV3nzSaTs1o2qemjbsrNysz0oRtzJSi7-yWq1UUlBxUo83K_ier92LV9FrXuLbS9UuHQPGwt1jkijlKvLP9mlbP2YzNvjKMLgJE8oaaQtaK7SsIFt5sRBJPGiW89zLLNPcSXEu24uPtUtq0qrMsLwyXEK2kMSqkUahNwcJFk5VyzrJFbyyKksQt5IQiSCMJBqTSJGkzIFnk8-MmbyZCIJJvLVirxgusIFjlt_MkklljhmicHLNl5bkO-zJkzEsfmJDMRKWQoF3sHqKOLlCqnB29lO8eflau7NcsZe607P3m3O7TSV5TNoq_PFRUk0k9I-9eTSXvK9215JpRS5lFp044rSa2uLZQyy7muVdfswli8iO4jt48s0bZjlVbdE-0qhw22ISiSWSylncNfm51AtdeZ5zyrbxtDdLJBFGIgd8jwgRR28VtbB5IMQQO4dxCxq_JdQX-pzAW4i8uW0RorpmlijWC6nvECSy3Eio53RPcQRsiyI8Vt9midJhJnecbadpInAhHl-RgEMv3LmSRXYSiE-ZHLLcxBmiuNgSPyopZRWMVBTdS2vNJaK15LlfvtSakm3zJtrVyu2mxOnFJpKPIlGNmlyaSVuitsm1y2WsWk7SGR2sAiEZuBOkTIpKSCQkkO1mrSqnFwJQGhME6xK20LHCiqKzZRZweWGhmwWQJIZnfj7TcyEyOvlK0Zmd5Y1VWfbiOaJ5lEraViJFP21PKNtBK1u82HAW6At1iSC3ZZJJI5UYNCIVOQ8shWUNkJJHFIsSEKI0gjjIi3xFGSS5miUJFJIGDPOS0m5Wc7W2vMwek4OUb-zteLellLdpK8m2leSbak9EtWrXnlfO3BpctOmuVt6-80rWV9oK8r6XdoKXNKUcttLI4u3KyPIskjMWYO7xJC3zbQyxgxwxuwjiZUiIeJwyuGdFDF5uYLdlneK23RRyrtzCjIFZVD4QYmRHRlEkZjO2JEK1dhLtNPbLGyF4pEZJ2kt0CwRvHcrK6oHMJiJikERGwTRSEIzLuSaO3tlkjLK5ktpHg8iWAc-ZbNJLHMgEwBkVxiJgV2o8qNI0NwmEnytfE3GWzXvJR50kle8do83bmjbmamawcrJKMbKMIq891ZaNJaPzTbd47_E47vzpwLi6V7p_NidSsvluX23NuAkZ6edEoVGkURLsVQWdWxcKCLUApWRN1rfRzTb98sGI5k8ueJJflHkSMiYZwzqnmRMC8NQW1xqNxPKxDC0xEXeeb92Jm8yCGVJJhJIlqgtFV1k8yGZo7VFiyBvnM6ywyrdmSNrZZZLtjNabZLpZLvykYNJHKFjhVI7kwyMUXb5GQi5zi4qyStH2kWlJNrSLUW4305tdVfTdNyuaQejTurrl5veu3zwbbsrRjJKyacpSjrzWabdb6e1_cPMpS1lt_JZ0mmPlxokDT20xmWCWVDHDFb5idCsrSSxTRAE10cdx5kTC3ZkV5WjtWVoRLFLBKht2YyIFQSyi4splZQYHUS-XgRha1lZyaesyElblZwHd3lmEzRyNsETLcTx2SIlsoVwqANFJGWdBHueljOgguZ7i5juBe_bp5lvbl5be5uWAylzYSNLCwNrATCiSz_ZI3iW3kKxwFKfLz8sIp-0TSSja6sm-VK1uflk3e6bdpNuSKin7ic4XktG1G8XeKSbblyqySXuqz5dY81yWxsbsvOMB1hvoo7iUeVJm4nn3bYik7h2m3IkLQRxEyDzgqOZCl6ITxsJL2fNssyb2Mq2iPJNcON4S6kSPCtM0cc0BkjixerKWid5HrPq-n6TFd3U0Ux8tGCQpPullvpEljiUyraRj_RhHFcb7neixeUI1MjTQ1wcMmpePbuexs1aa1ijjiuY44LgwxpK0sO55LuOBUN4ZGhtbcZupCDczW4iaVkzxmIpQo1MROUoOCtN1YSVOFOCUYSjLmUpN2s_dfvRgr3i2_RwlOdSKjBN6LmaTjFLa8nytRtyQevSTim2pyNnV_iJPZahBbeHYo9QD3BNzLPdyxw3Lq90LcpH5vmhoTMonjX_XxXFypuH3slel_Bv9mnxz8UdctfN0y-tmlaWT7DPb-a0cNtdQygziJ41tp").execute();
} catch (IOException e) {
e.printStackTrace();
}
I tried that but same problem:
String encodedImage = new String(Base64.encodeBase64URLSafeString(byteArray));
String encodedImage = Base64.encodeBase64URLSafeString(byteArray);
Only hard instanciation seems to work :
String encodedImage = "_9j_4AAQSkZJRgABAQAAAQABAAD_2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH_2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH_wAARCAUAAtADASIAAhEBAxEB_8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL_8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4-Tl5ufo6erx8vP09fb3-Pn6_8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL_8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3-Pn6_9oADAMBAAIRAxEAPwD7T-H1zNcRW0NpvF0zqpvXk82MwyLKr-UgVSXMEyw3BlMkhCq-Y44pJH7Txd4Tu4bRdVtVl1N7iF40aCQYgt_OvZGRWWMpGRK0kYVBvkljJkUHyWHg3wg8TSTQWxt0WM2U7uk0il7e4tWjCuggMk8yPiCViC3kidBBlJFct91x3WneINKYsomQovlxRlcRCTLGZ4x5ojcTqjBAsZYusJZ1QAfnUI06cIwpSVOnSknTkoq6UW-Rxh765oLVuTdnJNas-RxEJNyvCpFJLWblf4oy97eSXu2Xk4t6uz_I342eEtUudO1po1NjBGtrLN5ywYe5jurowRZVCxdFhjnk3xMy3E8UyTGNXU_k18WvCbz3275PtkkTgzi6hnilF3byyxWcqSCCW3L3MG-aR1EU90EluAYhPLH_AES_GTwULbS9Xu7GKGeyng3GWSLzpo51WWa5TUY4C2-OFseVOQA6oYfLicxu34wftAeBRosZlKQPbahNFMkzXICxSrNMsivHOyTKZpoJI7d2SNJRvVAPLuBXq4erSjVV6rqSlCKmqkpNpuaa5E37t7cya15rSam1d5WurTUZW5XrHtfmTV73fNayV3zK8rJ2_Inxb4ZtLiW50zUrOUveK8dndrPHBAPneG7uZrbdPdNDLaRyeQ7TqFuxbcOZnQeUahZySTQLcSRS3NmstirQSQtYtFZPLIksMEyl47d5CZXkuIVEs0zyxqsgdj9P-LNHihubyK7R2NpdbEVlElvc2NwUe3uoyCJIp7O4ZIJleQvL56vaxiJLgx_PfibTLa1ubu7MiyWsCMbYRxg_ZgDM0VtvkuPuPO8kSSrEVXzY4gGIGfTpSao8sVJ35W73jyxlKUownZtXSvyt2k21z1JO0X106UJJyvBpWWkVJNQbjH3bJ2WrXK9XJp3cVJ-fXVmdUs7mV4AtoqmSTyobiezUokcVpdTpIZhbqtyBNPZLGsUjG5UShVmu2yDZaXLA_ny75fMtljdoCG8uPe0kkTFZVlaHdJL5G6QohuXZsb_O0bh7v7DPYQKLZ5_s5vHRZoil1Yz3qW21YkRDafZ47GYTTboh9pMZWOIPGufO3mRrJOp82MM1u0TxRp5DbwsEcZWZSu4Mkc-VmjV549pWOUN0RqyTdk4q0XHV3nzSaTs1o2qemjbsrNysz0oRtzJSi7-yWq1UUlBxUo83K_ier92LV9FrXuLbS9UuHQPGwt1jkijlKvLP9mlbP2YzNvjKMLgJE8oaaQtaK7SsIFt5sRBJPGiW89zLLNPcSXEu24uPtUtq0qrMsLwyXEK2kMSqkUahNwcJFk5VyzrJFbyyKksQt5IQiSCMJBqTSJGkzIFnk8-MmbyZCIJJvLVirxgusIFjlt_MkklljhmicHLNl5bkO-zJkzEsfmJDMRKWQoF3sHqKOLlCqnB29lO8eflau7NcsZe607P3m3O7TSV5TNoq_PFRUk0k9I-9eTSXvK9215JpRS5lFp044rSa2uLZQyy7muVdfswli8iO4jt48s0bZjlVbdE-0qhw22ISiSWSylncNfm51AtdeZ5zyrbxtDdLJBFGIgd8jwgRR28VtbB5IMQQO4dxCxq_JdQX-pzAW4i8uW0RorpmlijWC6nvECSy3Eio53RPcQRsiyI8Vt9midJhJnecbadpInAhHl-RgEMv3LmSRXYSiE-ZHLLcxBmiuNgSPyopZRWMVBTdS2vNJaK15LlfvtSakm3zJtrVyu2mxOnFJpKPIlGNmlyaSVuitsm1y2WsWk7SGR2sAiEZuBOkTIpKSCQkkO1mrSqnFwJQGhME6xK20LHCiqKzZRZweWGhmwWQJIZnfj7TcyEyOvlK0Zmd5Y1VWfbiOaJ5lEraViJFP21PKNtBK1u82HAW6At1iSC3ZZJJI5UYNCIVOQ8shWUNkJJHFIsSEKI0gjjIi3xFGSS5miUJFJIGDPOS0m5Wc7W2vMwek4OUb-zteLellLdpK8m2leSbak9EtWrXnlfO3BpctOmuVt6-80rWV9oK8r6XdoKXNKUcttLI4u3KyPIskjMWYO7xJC3zbQyxgxwxuwjiZUiIeJwyuGdFDF5uYLdlneK23RRyrtzCjIFZVD4QYmRHRlEkZjO2JEK1dhLtNPbLGyF4pEZJ2kt0CwRvHcrK6oHMJiJikERGwTRSEIzLuSaO3tlkjLK5ktpHg8iWAc-ZbNJLHMgEwBkVxiJgV2o8qNI0NwmEnytfE3GWzXvJR50kle8do83bmjbmamawcrJKMbKMIq891ZaNJaPzTbd47_E47vzpwLi6V7p_NidSsvluX23NuAkZ6edEoVGkURLsVQWdWxcKCLUApWRN1rfRzTb98sGI5k8ueJJflHkSMiYZwzqnmRMC8NQW1xqNxPKxDC0xEXeeb92Jm8yCGVJJhJIlqgtFV1k8yGZo7VFiyBvnM6ywyrdmSNrZZZLtjNabZLpZLvykYNJHKFjhVI7kwyMUXb5GQi5zi4qyStH2kWlJNrSLUW4305tdVfTdNyuaQejTurrl5veu3zwbbsrRjJKyacpSjrzWabdb6e1_cPMpS1lt_JZ0mmPlxokDT20xmWCWVDHDFb5idCsrSSxTRAE10cdx5kTC3ZkV5WjtWVoRLFLBKht2YyIFQSyi4splZQYHUS-XgRha1lZyaesyElblZwHd3lmEzRyNsETLcTx2SIlsoVwqANFJGWdBHueljOgguZ7i5juBe_bp5lvbl5be5uWAylzYSNLCwNrATCiSz_ZI3iW3kKxwFKfLz8sIp-0TSSja6sm-VK1uflk3e6bdpNuSKin7ic4XktG1G8XeKSbblyqySXuqz5dY81yWxsbsvOMB1hvoo7iUeVJm4nn3bYik7h2m3IkLQRxEyDzgqOZCl6ITxsJL2fNssyb2Mq2iPJNcON4S6kSPCtM0cc0BkjixerKWid5HrPq-n6TFd3U0Ux8tGCQpPullvpEljiUyraRj_RhHFcb7neixeUI1MjTQ1wcMmpePbuexs1aa1ijjiuY44LgwxpK0sO55LuOBUN4ZGhtbcZupCDczW4iaVkzxmIpQo1MROUoOCtN1YSVOFOCUYSjLmUpN2s_dfvRgr3i2_RwlOdSKjBN6LmaTjFLa8nytRtyQevSTim2pyNnV_iJPZahBbeHYo9QD3BNzLPdyxw3Lq90LcpH5vmhoTMonjX_XxXFypuH3slel_Bv9mnxz8UdctfN0y-tmlaWT7DPb-a0cNtdQygziJ41tp";
For the moment I can't send image to my backend API because there is a bug I don't know where... Anyone had already get this error ?
The problem was I had a heap size overflow, so convert image in base64 was not a good idea..
You can only send messages no longer than 1MB. If you want to store larger files (including images) you should use Blobstore. Here is a good explanation how to use Blobstore for Java with examples.
Then you just store blobKey in your Datastore and serve it from Blobstore using servlets if needed.

How to get the size of the data received via EXTRA_STREAM in an application handling the action send intent?

When another application is sending a file to my app, I get a Uri via the intent.getExtras().get(EXTRA_STREAM) property. I can then get the bytes of the file using an inputstream : new BufferedInputStream(activity.getContentResolver().openInputStream(uri));
Everything's OK and working so far. Now I'd like to show some kind of progress to my user, but I'm not sure of how to get the total number of bytes of the file without reading the stream completely beforehand (which would defeat the whole purpose of the progress bar) ...
I tried ParcelFileDescriptor fileDesc = activity.getContentResolver().openFileDescriptor(uri, "r"); but this only works with uris of type file://....
For example If I receive a file from Skydrive I get a content://.. Uri, as in : content://com.microsoft.skydrive.content.external/external_property/10C32CC94ECB90C4!155/Sunset.480p.mp4
On such Uri I get (unsurprisingly) a "FileNotFoundException : Not a whole file" exception.
Any sure fire way to get the total size of the stream of data I will get ?
Even though InputStream.available() is (almost) never a recommended way of getting file size, it might be a viable solution in your case.
The content is already available locally. A server is not involved. So, the following should return the exact file size:
try {
InputStream inputStream = getContentResolver().openInputStream(uri);
Log.i("TEST", "File Size: " + inputStream.available());
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
I tested this with SkyDrive and Dropbox. The file sizes returned were correct.
There is no general solution for getting the size of a stream, other than reading the entire stream. This is easily proven: One could create a web server that, for some URL, generates a random stream of text that is terminated at a random time. (In fact, I'm sure such URLs exist, whether by design or not :-) In such a case, the size of the stream isn't known until the last byte has been generated, never mind received.
So, the stream size, if it is sent by the server at all, has to be sent in an application-specific manner.
I've never worked with SkyDrive, but a google search for its API turned up this link, which has the following example for Android Java apps:
public void readFile() {
String fileId = "file.a6b2a7e8f2515e5e.A6B2A7E8F2515E5E!141";
client.getAsync(fileId, new LiveOperationListener() {
public void onError(LiveOperationException exception, LiveOperation operation) {
resultTextView.setText("Error reading file: " + exception.getMessage());
}
public void onComplete(LiveOperation operation) {
JSONObject result = operation.getResult();
String text = "File info:" +
"\nID = " + result.optString("id") +
"\nName = " + result.optString("name");
resultTextView.setText(text);
}
});
}
Based on other examples on that page, I would guess that something like result.optString("size") (or maybe result.optInt("size") ?) would give you the size of the file.

Open raw text recourse and diplay wrong next line

InputStream inputStream = getResources().openRawResource(idtext);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
String myText = "";
int in;
try {
in = inputStream.read();
while (in != -1) {
byteArrayOutputStream.write(in);
in = inputStream.read();
}
inputStream.close();
myText = byteArrayOutputStream.toString();
} catch (IOException e) {
e.printStackTrace();
}
myTextView.setText(myText); `
My code is used to display long text file in raw res. I don't know why, but some of text file display wrong about next line, any help?
It would be good if you can share some sample display vs your expected output.
From the initial guess, it could be because of couple of reasons:
The encoding used in the text file. So, if you have written the text in ASCII and displaying it while using UTF-8 strings, it would mess up few things. This should be consistent.
Could be a good case of how line feeds are encoding in the file, like \r\n or just \n.
You can also try encapsulating your InputStream to FileReader and line reading streams which are more specialized in directly reading strings, rather than converting it.
You can probably use a library like Apache Commons IO to manage all the stuffs for you.

android webview encrypted content

I have an application that uses a webview in order to display content and the Javascript calls are the controller of my application.
In order to provide a level of security I obfuscated the code. This is not enough as I would like to encrypt the html and js files and then decrypt them at runtime. I packed the apk file with these resources encrypted with RC4 algorithm. When loading the files, I am decrypting the javascript files, load them and then decrypt the html file and load it. However this doesn't work as the webcontent displays a message in the form of: the web page at data:text/html might be temporarily down or it may have moved permanently, etc, etc.
I overloaded onLoadResource in order to see what content is loaded and I can see it loads the Javascript content, but the content loaded is html escaped also.
My questions are:
1. How to secure the html and javascript files (located in assets folder) in order to not be accessible?
2. In case my approach is correct, has anyone any idea on what I am doing wrong?
Thanks!
Below is the code that decrypts and loads the resources:
protected void loadWebContent() {
checkEncryptionEnabled();
loadJSFiles();
logger.info("Loaded js ... going for html");
loadAssetFile("www/index.html", "text/html");
}
private void loadJSFiles() {
String[] jsFilesArray = { "app.js", "iscroll.js", "iui.js", "json.js" };
for (String js : jsFilesArray) {
loadAssetFile("www/js/" + js, "application/javascript");
}
}
private void loadAssetFile(String filePath, String mimeType) {
AssetManager assetMgr = getAssets();
InputStream is = null;
try {
is = assetMgr.open(filePath);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] temp = new byte[512];
int bytesRead = -1;
while ((bytesRead = is.read(temp)) > 0) {
baos.write(temp, 0, bytesRead);
}
byte[] encrypted = baos.toByteArray();
String content = null;
/**
* true
* */
if (Config.ENCRYPTION_ENABLED) {
byte[] decrypted = new RC4Encrypter("rc4_key").rc4(encrypted);
content = new String(decrypted, "utf-8");
} else {
content = new String(encrypted, "utf-8");
}
/**
* The webview to use
* */
if("application/javascript".equals(mimeType)) {
webContent.loadUrl("javascript:" + content);
} else {
webContent.loadData(content, mimeType, "utf-8");
}
} catch (IOException ex) {
logger.error(null, ex);
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
}
found the answer for the second question question instead of: webContent.loadData(content, mimeType, "utf-8"); I used: webContent.loadDataWithBaseURL("file:///android_asset/www/", content, mimeType, "utf-8", null); Content is shown with no problems ... However, the first question kind of stands and not; but considering there was no answer for more than a year, I'll consider encrypting data is OK.
Data encryption is OK as long as you can also keep the decryption key confidential, which is not the case in the above code. The hardcoded decryption key can be easily spotted after decompiling the DEX files embedded inside the APK.
If you want to hide the application logic inside the HTML and JavaScript files and if that application logic doesn't require offline capabilities then you could outsource the code of that application logic on a server.
From here you have two choices:
Load the application code dynamically from the server whenever
you need it (and run the application code on the client).
Implement the application logic on the server side, e.g., as a
web service (and run the application code on the server, the client
knows only how to call the web service)
The short answer to your first question is that there is no methodology or technology to perfectly protect your application. I recommend to you to take a look at How to avoid reverse engineering of an APK file? for an overview of possible protection methods.

Fastest way to seek (skip) an inputstream with http protocol

I am making a download service of sorts, and it has the ability to resume a previous partial download. I am currently using the skip method like this
long skipped = 0;
while (skipped < track.getCacheFile().length()){
skipped += is.skip(track.getCacheFile().length()-skipped);
}
I just did a test and it took about 57 seconds seconds to skip 45 mb in an inputstream. I am curious how certain native code does this, for instance, the mediaplayer can seek to any part of a remote stream instantaneously. I realize that I do not have access to the same libraries, but can I achieve something similar.
btw, that test was on wifi. It is obviously much slower on normal data networks.
Update: very simple (thanks to below)
if (track.getCacheFile().length() > 0){
request.setHeader("Range","bytes="+track.getCacheFile().length()+"-");
}
If you are using http as a protocol to initiate your inputstream, you may try the RANGE header.
Take a look here :
http://www.west-wind.com/Weblog/posts/244.aspx
The problem with the skip method is that you have to read the data even if you skip them so you need to receive them. The best solution is probably to request the server only the part you want.
You can do it like this:
private InputStream getRemote(String url, long offset) {
try {
URLConnection cn = new URL( url ).openConnection();
cn.setRequestProperty ("Range", "bytes="+offset+"-");
cn.connect();
length = cn.getContentLength();
return cn.getInputStream();
} catch (MalformedURLException e ) { e.printStackTrace();
} catch (IOException e) { e.printStackTrace(); }
return null;
}
Then when you need to skip, you actually do a reconnect via HTTP to the new offset. Works quick and reliable, much better than using the inputstream's skip.

Categories

Resources