I am trying to calculate a download speed test calculate.
Found a lot info in Stackoverflow but nothing help me.
The final calculation is not logic.
Trying to know the download speed in the while thread.
Attached my code that I found.
public void run() {
OutputStream out = null;
URLConnection conn = null;
InputStream in = null;
try
{
URL url1 = new URL("test");
out = new BufferedOutputStream(new FileOutputStream(getVideoFile().getPath()));
conn = url1.openConnection();
in = conn.getInputStream();
long start = System.currentTimeMillis();
byte[] buffer = new byte[1024];
int numRead;
long numWritten = 0;
while ((numRead = in.read(buffer)) != -1)
{
out.write(buffer, 0, numRead);
numWritten += numRead;
long end = System.currentTimeMillis();
if ((end - start)>0) {
double rate = 1000f * numWritten / (end - start) ;
Log.d("downloadmanager","speed "+rate);
}
}
}
catch (Exception ex)
{
Log.d("downloadmanager","Unknown Error: " + ex);
}
finally
{
try
{
if (in != null)
{
in.close();
}
if (out != null)
{
out.close();
}
}
catch (IOException ex)
{
Log.d("downloadmanager", "Unknown Error: " + ex);
}
}
}
}).start();
Thanks for helping figure this up.
I have tried like this way, hope it will help!
The change is , I have used set of url's.
public class TestSpeed extends AsyncTask<Void,Void,Void> {
String TAG = "TestSpeed";
long startTime,endTime,contentLength;
String vURL[] = {
"http://test/url/file1",
"http://test/url/file2",
"http://test/url/file3",
"http://test/url/file4",
"http://test/url/file5",
"http://test/url/file6",
"http://test/url/file7"
"http://test/url/file8"
};
#Override
protected Void doInBackground(Void... params) {
setCall(vURL[GlobalData.URLIndex]);
GlobalData.URLIndex += 1;
if(GlobalData.URLIndex >= vURL.length){
GlobalData.URLIndex = 0;
}
return null;
}
void setCall(String URL){
try {
Log.d(TAG,"Start " + URL);
startTime = System.currentTimeMillis(); //Hold StartTime
HttpGet httpRequest = new HttpGet(new URL(URL).toURI());
HttpClient httpClient = new DefaultHttpClient();
HttpResponse response = (HttpResponse) httpClient.execute(httpRequest);
endTime = System.currentTimeMillis(); //Hold EndTime
HttpEntity entity = response.getEntity();
BufferedHttpEntity bufHttpEntity;
bufHttpEntity = new BufferedHttpEntity(entity);
//You can check the size of your file
contentLength = bufHttpEntity.getContentLength();
// Log
Log.d("TAG", "Dowload time :" + (endTime - startTime) + " ms");
// Speed : size(KB)/time(s)
Long mSpeed = contentLength / ((endTime - startTime) * 1000);
Log.d(TAG, "mSpeed :" + mSpeed);
Double duration = Double.valueOf((endTime - startTime));
Double speedKbps = Double.valueOf(roundTwoDecimals(Double.valueOf(contentLength / 1024)));
Double speedMbps = roundTwoDecimals(speedKbps / 1024);
Log.d(TAG,"" + speedKbps);
Log.d(TAG,"" + speedMbps);
//confirm units for display
String mTheSpeed = "" + speedMbps;
String speed;
if(mTheSpeed.charAt(0) == '0'){
speed = roundTwoDecimals(speedKbps) + " kb/s";
}else{
speed = roundTwoDecimals(speedMbps) + " mb/s";
}
Log.d("Speed Result: ","" + speed);
}catch (Exception ex){
ex.printStackTrace();
}
}
Double roundTwoDecimals(Double vLongValue)
{
DecimalFormat twoDForm = new DecimalFormat("#.###");
return Double.valueOf(twoDForm.format(vLongValue));
}
}
For an alternative you can go with the WifiInfo, the code looks like this.
private static Integer wifiSpeed(Context mContext){
WifiManager wifiManager = (WifiManager);
mContext.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiManager.getConnectionInfo();
Integer wifiSpeed = wifiInfo.getLinkSpeed();
return wifiSpeed;
}
Related
I am using a service to download files and extract them if they are archived.
The extraction method is wrapped as a asynctask to improve performance of the extraction process.
My problem is that when I run the app on the virtual device, all is fine and the extraction process is really fast but as soon as I test it on a real device (Nexus 9 tablet, Android 6x) the extraction process is really slow and takes minutes to complete.
Is there anything I can do, to speed up the extraction process?
I execute the asynctask with: new UnRarTask(targetAppName).execute();
Below the piece of code which is relevant:
public class DownloadTask implements Runnable {
private DownloadService service;
private DownloadManager downloadManager;
protected void init(DownloadService service, Intent intent) {
this.service = service;
downloadManager = (DownloadManager) MyApp_.getInstance().
getSystemService(Activity.DOWNLOAD_SERVICE);
DownloadRequest downloadRequest = intent.getParcelableExtra(DownloadService
.DOWNLOAD_REQUEST);
}
private class UnRarTask extends AsyncTask<Void, Integer, String> {
String rarPath = null;
int countRar = 0;
long copiedbytes = 0, totalbytes = 0;
Archive archive = null;
FileHeader fileHeader = null;
File archiveFile;
List<FileHeader> headers;
UnRarTask(String one) {
this.archiveFile = new File(one);
}
#Override
protected String doInBackground(Void... params) {
try {
archive = new Archive(new FileVolumeManager(archiveFile));
} catch (RarException | IOException e) {
e.printStackTrace();
}
String fileName = archiveFile.getName();
String absolutePath = archiveFile.getAbsolutePath();
String archiveDirectoryFileName = absolutePath.substring(0, absolutePath.indexOf(fileName));
if (archive != null) {
fileHeader = archive.nextFileHeader();
headers = archive.getFileHeaders();
for (FileHeader fh : headers) {
totalbytes = totalbytes + fh.getFullUnpackSize();
}
}
while (fileHeader != null) {
BufferedInputStream inputStream;
try {
inputStream = new BufferedInputStream(archive.getInputStream(fileHeader));
String extractedFileName = fileHeader.getFileNameString().trim();
String fullExtractedFileName = archiveDirectoryFileName + extractedFileName;
File extractedFile = new File(fullExtractedFileName);
FileOutputStream fileOutputStream = new FileOutputStream(extractedFile);
BufferedOutputStream flout = new BufferedOutputStream(fileOutputStream, BUFFER_SIZE);
if (extractedFile.getName().toLowerCase().endsWith(".mp3")
|| extractedFile.getName().toLowerCase().endsWith(".epub")
|| extractedFile.getName().toLowerCase().endsWith(".pdf")
|| extractedFile.getName().toLowerCase().endsWith(".mobi")
|| extractedFile.getName().toLowerCase().endsWith(".azw3")
|| extractedFile.getName().toLowerCase().endsWith(".m4b")
|| extractedFile.getName().toLowerCase().endsWith(".apk")) {
rarPath = extractedFile.getPath();
countRar++;
}
int len;
byte buf[] = new byte[BUFFER_SIZE];
while ((len = inputStream.read(buf)) > 0) {
//fileOutputStream.write(buf, 0, len);
copiedbytes = copiedbytes + len;
int progress = (int) ((copiedbytes / (float) totalbytes) * 100);
if (progress > lastProgress) {
lastProgress = progress;
service.showUpdateProgressNotification(downloadId, appName, progress,
"Extracting rar archive: " + lastProgress + " % completed", downloadStart);
}
}
archive.extractFile(fileHeader, flout);
flout.flush();
flout.close();
fileOutputStream.flush();
fileOutputStream.close();
inputStream.close();
fileHeader = archive.nextFileHeader();
} catch (RarException | IOException e) {
e.printStackTrace();
}
}
if (countRar == 0) {
filePath = "Error";
broadcastFailed();
}
if (copiedbytes == totalbytes) {
if (archive != null)
archive.close();
}
return null;
}
}
}
How to upload a video to a particular YouTube account from my android app i have followed https://github.com/youtube/yt-direct-lite-android but its not very documented.
I have tried
public class YoutubeUploader {
private static final String TAG = "YoutubeUploader";
// After creating project at http://www.appspot.com DEFAULT_YTD_DOMAIN == <Developers Console Project ID>.appspot.com [ You can find from Project -> Administration -> Application settings]
//public static final String DEFAULT_YTD_DOMAIN = "developerconsolid.appspot.com";
// I used Google APIs Console Project Title as Domain name:
//public static final String DEFAULT_YTD_DOMAIN_NAME = "Domain Name";
//From Google Developer Console from same project (Created by SHA1; project package)
//Example https://console.developers.google.com/project/apps~gtl-android-youtube-test/apiui/credential
public static final String DEVELOPER_KEY = "<MY_DEVELOPER_KEY>";
// CLIENT_ID == Google APIs Console Project Number:
public static final String CLIENT_ID = "157613";
public static final String YOUTUBE_AUTH_TOKEN_TYPE = "youtube";
private static final String AUTH_URL = "https://www.google.com/accounts/ClientLogin";
// Uploader's user-name and password
private static final String USER_NAME = "my#gmail.com";
private static final String PASSWORD = "mypassword";
private static final String INITIAL_UPLOAD_URL = "https://uploads.gdata.youtube.com/resumable/feeds/api/users/default/uploads";
private static String getClientAuthToken() {
try {
URL url = new URL(AUTH_URL);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String template = "Email=%s&Passwd=%s&service=%s&source=%s";
String userName = USER_NAME; // TODO
String password = PASSWORD; // TODO
String service = YOUTUBE_AUTH_TOKEN_TYPE;
String source = CLIENT_ID;
userName = URLEncoder.encode(userName, "UTF-8");
password = URLEncoder.encode(password, "UTF-8");
String loginData = String.format(template, userName, password, service, source);
OutputStreamWriter outStreamWriter = new OutputStreamWriter(urlConnection.getOutputStream());
outStreamWriter.write(loginData);
outStreamWriter.close();
int responseCode = urlConnection.getResponseCode();
if (responseCode != 200) {
Log.d(TAG, "Got an error response : " + responseCode + " " + urlConnection.getResponseMessage());
throw new IOException(urlConnection.getResponseMessage());
} else {
InputStream is = urlConnection.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
if (line.startsWith("Auth=")) {
String split[] = line.split("=");
String token = split[1];
Log.d(TAG, "Auth Token : " + token);
return token;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String upload(YoutubeUploadRequest uploadRequest, ProgressListner listner, Activity activity) {
totalBytesUploaded = 0;
String authToken = getClientAuthToken();
if(authToken != null) {
String uploadUrl = uploadMetaData(uploadRequest, authToken, activity, true);
File file = getFileFromUri(uploadRequest.getUri(), activity);
long currentFileSize = file.length();
int uploadChunk = 1024 * 1024 * 3; // 3MB
int start = 0;
int end = -1;
String videoId = null;
double fileSize = currentFileSize;
while (fileSize > 0) {
if (fileSize - uploadChunk > 0) {
end = start + uploadChunk - 1;
} else {
end = start + (int) fileSize - 1;
}
Log.d(TAG, String.format("start=%s end=%s total=%s", start, end, file.length()));
try {
videoId = gdataUpload(file, uploadUrl, start, end, authToken, listner);
fileSize -= uploadChunk;
start = end + 1;
} catch (IOException e) {
Log.d(TAG,"Error during upload : " + e.getMessage());
}
}
if (videoId != null) {
return videoId;
}
}
return null;
}
public static int totalBytesUploaded = 0;
#SuppressLint("DefaultLocale")
#SuppressWarnings("resource")
private static String gdataUpload(File file, String uploadUrl, int start, int end, String clientLoginToken, ProgressListner listner) throws IOException {
int chunk = end - start + 1;
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
FileInputStream fileStream = new FileInputStream(file);
URL url = new URL(uploadUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("Authorization", String.format("GoogleLogin auth=\"%s\"", clientLoginToken));
urlConnection.setRequestProperty("GData-Version", "2");
urlConnection.setRequestProperty("X-GData-Client", CLIENT_ID);
urlConnection.setRequestProperty("X-GData-Key", String.format("key=%s", DEVELOPER_KEY));
// some mobile proxies do not support PUT, using X-HTTP-Method-Override to get around this problem
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("X-HTTP-Method-Override", "PUT");
urlConnection.setDoOutput(true);
urlConnection.setFixedLengthStreamingMode(chunk);
urlConnection.setRequestProperty("Content-Type", "video/3gpp");
urlConnection.setRequestProperty("Content-Range", String.format("bytes %d-%d/%d", start, end,
file.length()));
Log.d(TAG, urlConnection.getRequestProperty("Content-Range"));
OutputStream outStreamWriter = urlConnection.getOutputStream();
fileStream.skip(start);
double currentFileSize = file.length();
int bytesRead;
int totalRead = 0;
while ((bytesRead = fileStream.read(buffer, 0, bufferSize)) != -1) {
outStreamWriter.write(buffer, 0, bytesRead);
totalRead += bytesRead;
totalBytesUploaded += bytesRead;
double percent = (totalBytesUploaded / currentFileSize) * 100;
if(listner != null){
listner.onUploadProgressUpdate((int) percent);
}
System.out.println("GTL You tube upload progress: " + percent + "%");
/*
Log.d(LOG_TAG, String.format(
"fileSize=%f totalBytesUploaded=%f percent=%f", currentFileSize,
totalBytesUploaded, percent));
*/
//dialog.setProgress((int) percent);
// TODO My settings
if (totalRead == (end - start + 1)) {
break;
}
}
outStreamWriter.close();
int responseCode = urlConnection.getResponseCode();
Log.d(TAG, "responseCode=" + responseCode);
Log.d(TAG, "responseMessage=" + urlConnection.getResponseMessage());
try {
if (responseCode == 201) {
String videoId = parseVideoId(urlConnection.getInputStream());
return videoId;
} else if (responseCode == 200) {
Set<String> keySet = urlConnection.getHeaderFields().keySet();
String keys = urlConnection.getHeaderFields().keySet().toString();
Log.d(TAG, String.format("Headers keys %s.", keys));
for (String key : keySet) {
Log.d(TAG, String.format("Header key %s value %s.", key, urlConnection.getHeaderField(key)));
}
Log.w(TAG, "Received 200 response during resumable uploading");
throw new IOException(String.format("Unexpected response code : responseCode=%d responseMessage=%s", responseCode,
urlConnection.getResponseMessage()));
} else {
if ((responseCode + "").startsWith("5")) {
String error = String.format("responseCode=%d responseMessage=%s", responseCode,
urlConnection.getResponseMessage());
Log.w(TAG, error);
// TODO - this exception will trigger retry mechanism to kick in
// TODO - even though it should not, consider introducing a new type so
// TODO - resume does not kick in upon 5xx
throw new IOException(error);
} else if (responseCode == 308) {
// OK, the chunk completed succesfully
Log.d(TAG, String.format("responseCode=%d responseMessage=%s", responseCode,
urlConnection.getResponseMessage()));
} else {
// TODO - this case is not handled properly yet
Log.w(TAG, String.format("Unexpected return code : %d %s while uploading :%s", responseCode,
urlConnection.getResponseMessage(), uploadUrl));
}
}
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
return null;
}
private static String parseVideoId(InputStream atomDataStream) throws ParserConfigurationException,
SAXException, IOException {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse(atomDataStream);
NodeList nodes = doc.getElementsByTagNameNS("*", "*");
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
String nodeName = node.getNodeName();
if (nodeName != null && nodeName.equals("yt:videoid")) {
return node.getFirstChild().getNodeValue();
}
}
return null;
}
private static File getFileFromUri(Uri uri, Activity activity) {
try {
String filePath = null;
String[] proj = { Video.VideoColumns.DATA };
Cursor cursor = activity.getContentResolver().query(uri, proj, null, null, null);
if(cursor.moveToFirst()) {
int column_index = cursor.getColumnIndexOrThrow(Video.VideoColumns.DATA);
filePath = cursor.getString(column_index);
}
cursor.close();
//String filePath = cursor.getString(cursor.getColumnIndex(Video.VideoColumns.DATA));
File file = new File(filePath);
cursor.close();
return file;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String uploadMetaData(YoutubeUploadRequest uploadRequest, String clientLoginToken, Activity activity, boolean retry) {
try {
File file = getFileFromUri(uploadRequest.getUri(), activity);
if(file != null) {
String uploadUrl = INITIAL_UPLOAD_URL;
URL url = new URL(uploadUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestProperty("Authorization", String.format("GoogleLogin auth=\"%s\"", clientLoginToken));
connection.setRequestProperty("GData-Version", "2");
connection.setRequestProperty("X-GData-Client", CLIENT_ID);
connection.setRequestProperty("X-GData-Key", String.format("key=%s", DEVELOPER_KEY));
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Content-Type", "application/atom+xml");
connection.setRequestProperty("Slug", file.getAbsolutePath());
String title = uploadRequest.getTitle();
String description = uploadRequest.getDescription();
String category = uploadRequest.getCategory();
String tags = uploadRequest.getTags();
String template = readFile(activity, R.raw.gdata).toString();
String atomData = String.format(template, title, description, category, tags);
/*String template = readFile(activity, R.raw.gdata_geo).toString();
atomData = String.format(template, title, description, category, tags,
videoLocation.getLatitude(), videoLocation.getLongitude());*/
OutputStreamWriter outStreamWriter = new OutputStreamWriter(connection.getOutputStream());
outStreamWriter.write(atomData);
outStreamWriter.close();
int responseCode = connection.getResponseCode();
if (responseCode < 200 || responseCode >= 300) {
// The response code is 40X
if ((responseCode + "").startsWith("4") && retry) {
Log.d(TAG, "retrying to fetch auth token for ");
clientLoginToken = getClientAuthToken();
// Try again with fresh token
return uploadMetaData(uploadRequest, clientLoginToken, activity, false);
} else {
return null;
}
}
return connection.getHeaderField("Location");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static CharSequence readFile(Activity activity, int id) {
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(activity.getResources().openRawResource(id)));
String line;
StringBuilder buffer = new StringBuilder();
while ((line = in.readLine()) != null) {
buffer.append(line).append('\n');
}
// Chomp the last newline
buffer.deleteCharAt(buffer.length() - 1);
return buffer;
} catch (IOException e) {
return "";
} finally {
closeStream(in);
}
}
/**
* Closes the specified stream.
*
* #param stream The stream to close.
*/
private static void closeStream(Closeable stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
// Ignore
}
}
}
public static interface ProgressListner {
void onUploadProgressUpdate(int progress);
}
I am getting 404 error in getClientAuthToken() method.I think "https://www.google.com/accounts/ClientLogin";deprecated by google any alternative to this
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 am trying to send the send voice data immediately to local server using audiorecord.. I am able to record the voice & stores it in SDcard.. but I want to store audio voice in buffer & sends immediate to the server using HTTP POST. How can I proceed.got struck..? I am creating this app in ICS i.e android 4.0.3 version.
got the solutions.. sending voice data as a jsonarray to server & recieve back as a json object. convert back jsonobject to short array n write to audiotrack then play back. here is sample code working.
public void SendAudio() {
String LOG_TAG = null;
long SAMPLE_INTERVAL = 1;
Log.e(LOG_TAG, "start send thread, thread id: ");
int bytes_read = 0;
int bytes_count = 0;
br = br % 5;
br++;
try {
HttpClient httpclient = new DefaultHttpClient();
HttpClient httpclient_recv = new DefaultHttpClient();
// System.out.println("mmdata--------- " + value);
HttpPost httppost = new HttpPost("http://192.168.1.39/call");
HttpPost httppost_recv = new HttpPost("http://192.168.1.39/ping");
// Unix time stamp
long unixTime = System.currentTimeMillis();
String timestamp = String.valueOf(unixTime);
// Json Format
JSONObject holder = new JSONObject();
JSONObject holder_recv = new JSONObject();
JSONArray jArray = new JSONArray();
try {
holder.put("UserId", "1");
holder.put("TimeStamp", timestamp);
holder.put("SessionId", "1");
Queue<byte[]> qArray = new LinkedList<byte[]>();
qArray.add(bData);
byte[] tmparr = qArray.poll();
for (int i = 0; i < tmparr.length; i++) {
jArray.put(i, tmparr[i]);
}
System.out.println("send audio -- " + jArray);
holder.put("MMData", jArray.toString());
System.out.println("JSON -- " + holder.toString());
holder_recv.put("UserId", "1");
holder_recv.put("TimeStamp", timestamp);
holder_recv.put("SeqNo", "100");
holder_recv.put("SessionId", "0");
} catch (JSONException e1) {
e1.printStackTrace();
}
System.out.println("time " + timestamp);
try {
StringEntity se = new StringEntity(holder.toString());
StringEntity se_recv = new StringEntity(holder_recv.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE,
"application/json"));
se_recv.setContentType(new BasicHeader(HTTP.CONTENT_TYPE,
"application/json"));
httppost.setEntity(se);
httppost_recv.setEntity(se_recv);
HttpResponse response = httpclient.execute(httppost);
HttpResponse response_recv = httpclient_recv
.execute(httppost_recv);
if (response_recv != null) {
t = EntityUtils.toString(response_recv.getEntity());
System.out.println("after response -- " + t);
Queue<String> qe = new LinkedList<String>();
qe.add(t);
t = null;
System.out.println("on play side ...1 ");
try {
System.out.println("on play side ...2 ");
JSONObject get = new JSONObject(qe.poll());
// JSONArray jArray_recv = get.getJSONArray("MMData");
String mmdata = (String) get.get("MMData");
JSONObject temp2 = new JSONObject("{ \"MMData\" : "
+ mmdata + "}");
JSONArray jArray_recv = temp2.getJSONArray("MMData");
System.out.println("jsonarray -- " + jArray_recv);
// String timeData = (String) get.get("TimeStamp");
String userData = (String) get.get("UserId");
// String sessionId = (String) get.get("TimeStamp");
System.out.println("on play side ...3 ");
// if (Long.valueOf(timeData) > ts)
{
// ts = Long.valueOf(timeData);
System.out.println("on play side ...4 ");
if (at != null) {
System.out.println("on play side ...5 ");
byte[] shortArray = new byte[jArray_recv
.length()];
for (int i = 0; i < jArray_recv.length(); i++) {
shortArray[i] = (byte) jArray_recv
.getInt(i);
}
jArray_recv = null;
System.out.println("recv audio -- " + br
+ " ----" + shortArray);
byte[] temp = shortArray;
shortArray = null;
byte[] bArray = temp;
temp = null;
byte[][] newbarray = new byte[5][1024];
newbarray[br - 1] = bArray;
byte[] sbayyay = new byte[1024 * 5];
System.arraycopy(bArray, 0, sbayyay,
(br - 1) * 1024, bArray.length);
if (br == 5) {
for (int i = 0; i < 5; i++) {
System.out.println("in for---" + i
+ "----" + sbayyay.length);
// System.arraycopy(newbarray[i], 0,
// sbayyay, i * 1024,
// bArray.length);
}
System.out.println("bsbsbsbs --- "
+ new String(sbayyay));
at.write(sbayyay, 0, sbayyay.length);
at.play();
}
}
else {
Log.d("Audio",
"audio track is not initialised ");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
System.out.println("Exception");
e.printStackTrace();
}
bytes_count += bytes_read;
Log.d(LOG_TAG, "bytes_count : " + bytes_count);
Thread.sleep(SAMPLE_INTERVAL, 0);
} catch (InterruptedException ie) {
Log.e(LOG_TAG, "InterruptedException");
}
}
I am getting JSON data from a web service and would like to display a progress bar while the data is downloading. All the examples I have seen use a StringBuilder like so:
//Set up the initial connection
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setReadTimeout(10000);
connection.connect();
InputStream stream = connection.getInputStream();
//read the result from the server
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder builder = new StringBuilder();
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line + '\n');
}
result = builder.toString();
I got the ProgressBar to work by downloading the data as a byte array, then converting the byte array to a String, but I'm wondering if there is a 'more correct' way to do this. Since I've found no other way of doing this, the following class can also serve as a working example, seems a bit of a hack, but it does work well.
package com.royaldigit.newsreader.services;
import android.os.AsyncTask;
import android.util.Log;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.royaldigit.newsreader.controller.commands.CommandInterface;
import com.royaldigit.newsreader.model.data.SearchResultDO;
import com.royaldigit.newsreader.model.data.SearchTermDO;
/**
* Gets news results from Feedzilla based on the search term currently stored in model.searchTermDO
*
* Sends progress update and returns results to the CommandInterface command reference:
* * command.onProgressUpdate(progress);
* * command.serviceComplete(results);
*
*
*/
public class FeedzillaSearchService {
private static final String TAG = "FeedzillaSearchService";
private static final String SERVICE_URI = "http://api.feedzilla.com/v1/categories/26/articles/search.json?q=";
private static final int STREAM_DIVISIONS = 10;
private CommandInterface command;
private SearchTermDO currentSearchTermDO;
private Integer maximumResults;
private DownloadTask task;
private ArrayList<SearchResultDO> results;
public Boolean isCanceled = false;
public void getData(CommandInterface cmd, SearchTermDO termDO, Integer maxResults){
command = cmd;
currentSearchTermDO = termDO;
//Feedzilla only allows count to be 100 or less, anything over throws an error
maximumResults = (maxResults > 100)? 100 : maxResults;
results = new ArrayList<SearchResultDO>();
task = new DownloadTask();
task.execute();
}
public void cancel() {
isCanceled = true;
if(task != null) task.cancel(true);
}
/**
* Handle GET request
*
*/
private class DownloadTask extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void...voids) {
String result = "";
if(currentSearchTermDO == null || currentSearchTermDO.term.equals("")) return result;
BufferedReader reader = null;
publishProgress(0);
try {
String path = SERVICE_URI + URLEncoder.encode(currentSearchTermDO.term, "UTF-8") + "&count=" + maximumResults;
Log.d(TAG, "path = "+path);
URL url = new URL(path);
//Set up the initial connection
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setReadTimeout(10000);
connection.connect();
int length = connection.getContentLength();
InputStream stream = connection.getInputStream();
byte[] data = new byte[length];
int bufferSize = (int) Math.ceil(length / STREAM_DIVISIONS);
int progress = 0;
for(int i = 1; i < STREAM_DIVISIONS; i++){
int read = stream.read(data, progress, bufferSize);
progress += read;
publishProgress(i);
}
stream.read(data, progress, length - progress);
publishProgress(STREAM_DIVISIONS);
result = new String(data);
} catch (Exception e) {
Log.e(TAG, "Exception "+e.toString());
} finally {
if(reader != null){
try {
reader.close();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
int currentProgress = progress[0] * 100/STREAM_DIVISIONS;
if(!this.isCancelled()) command.onProgressUpdate(currentProgress);
}
#Override
protected void onPostExecute(String result){
if(!this.isCancelled()) downloadTaskComplete(result);
}
}
/**
*
* #param data
*/
private void downloadTaskComplete(Object data){
if(!isCanceled){
try {
Log.d(TAG, data.toString());
JSONObject obj = new JSONObject(data.toString());
JSONArray array = obj.getJSONArray("articles");
for(int i = 0; i < array.length(); i++){
SearchResultDO dataObj = new SearchResultDO();
dataObj.title = array.getJSONObject(i).getString("title");
dataObj.url = array.getJSONObject(i).getString("url");
dataObj.snippet = array.getJSONObject(i).getString("summary");
dataObj.source = array.getJSONObject(i).getString("source");
dataObj.date = array.getJSONObject(i).getString("publish_date");
dataObj.termId = currentSearchTermDO.id;
//Reformat date
SimpleDateFormat format1 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
try {
Date date = format1.parse(dataObj.date);
SimpleDateFormat format2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dataObj.date = format2.format(date);
} catch(ParseException pe) {
Log.e(TAG, pe.getMessage());
}
results.add(dataObj);
}
command.serviceComplete(results);
} catch(JSONException e){
Log.e(TAG, e.toString());
command.serviceComplete(results);
}
}
}
}
UPDATE: Here is the finished version of the class using the suggestions from Nikolay. I ended up using the StringBuilder after all. The previous version would break because some times connection.getContentLength() returns -1. This version degrades gracefully for that case. Tested this implementation quite a bit and it seems bulletproof.
package com.royaldigit.newsreader.services;
import android.os.AsyncTask;
import android.util.Log;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.royaldigit.newsreader.controller.commands.CommandInterface;
import com.royaldigit.newsreader.model.data.SearchResultDO;
import com.royaldigit.newsreader.model.data.SearchTermDO;
/**
* Gets news results from Feedzilla based on the search term currently stored in model.searchTermDO
*
* Sends progress update and returns results to the CommandInterface command reference:
* * command.onProgressUpdate(progress);
* * command.serviceComplete(results);
*
*/
public class FeedzillaSearchService implements SearchServiceInterface {
private static final String TAG = "FeedzillaSearchService";
private static final String SERVICE_URI = "http://api.feedzilla.com/v1/categories/26/articles/search.json?q=";
private CommandInterface command;
private SearchTermDO currentSearchTermDO;
private Integer maximumResults;
private DownloadTask task;
private ArrayList<SearchResultDO> results;
private Boolean isCanceled = false;
public void getData(CommandInterface cmd, SearchTermDO termDO, Integer maxResults){
command = cmd;
currentSearchTermDO = termDO;
//Feedzilla only allows count to be 100 or less, anything over throws an error
maximumResults = (maxResults > 100)? 100 : maxResults;
results = new ArrayList<SearchResultDO>();
task = new DownloadTask();
task.execute();
}
public void cancel() {
isCanceled = true;
if(task != null) task.cancel(true);
}
/**
* Handle GET request
*
*/
private class DownloadTask extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void...voids) {
String result = "";
if(currentSearchTermDO == null || currentSearchTermDO.term.equals("")) return result;
BufferedReader reader = null;
publishProgress(0);
try {
String path = SERVICE_URI + URLEncoder.encode(currentSearchTermDO.term, "UTF-8") + "&count=" + maximumResults;
Log.d(TAG, "path = "+path);
URL url = new URL(path);
//Set up the initial connection
HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("GET");
connection.setDoOutput(true);
connection.setReadTimeout(20000);
connection.connect();
//connection.getContentType() should return something like "application/json; charset=utf-8"
String[] values = connection.getContentType().toString().split(";");
String charset = "";
for (String value : values) {
value = value.trim();
if (value.toLowerCase().startsWith("charset=")) {
charset = value.substring("charset=".length());
break;
}
}
//Set default value if charset not set
if(charset.equals("")) charset = "utf-8";
int contentLength = connection.getContentLength();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder builder = new StringBuilder();
/**
* connection.getContentLength() can return -1 on some connections.
* If we have the content length calculate progress, else just set progress to 100 and build the string all at once.
*
*/
if(contentLength>-1){
//Odd byte array sizes don't always work, tried 512, 1024, 2048; 1024 is the magic number because it seems to work best.
byte[] data = new byte[1024];
int totalRead = 0;
int bytesRead = 0;
while ((bytesRead = stream.read(data)) > 0) {
try {
builder.append(new String(data, 0, bytesRead, charset));
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Invalid charset: " + e.getMessage());
//Append without charset (uses system's default charset)
builder.append(new String(data, 0, bytesRead));
}
totalRead += bytesRead;
int progress = (int) (totalRead * (100/(double) contentLength));
//Log.d(TAG, "length = " + contentLength + " bytesRead = " + bytesRead + " totalRead = " + totalRead + " progress = " + progress);
publishProgress(progress);
}
} else {
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line + '\n');
publishProgress(100);
}
}
result = builder.toString();
} catch (Exception e) {
Log.e(TAG, "Exception "+e.toString());
} finally {
if(reader != null){
try {
reader.close();
} catch(IOException ioe) {
ioe.printStackTrace();
}
}
}
return result;
}
protected void onProgressUpdate(Integer... progress) {
if(!this.isCancelled()) command.onProgressUpdate(progress[0]);
}
#Override
protected void onPostExecute(String result){
if(!this.isCancelled()) downloadTaskComplete(result);
}
}
/**
*
* #param data
*/
private void downloadTaskComplete(Object data){
if(!isCanceled){
try {
Log.d(TAG, data.toString());
JSONObject obj = new JSONObject(data.toString());
JSONArray array = obj.getJSONArray("articles");
for(int i = 0; i < array.length(); i++){
SearchResultDO dataObj = new SearchResultDO();
dataObj.title = array.getJSONObject(i).getString("title");
dataObj.url = array.getJSONObject(i).getString("url");
dataObj.snippet = array.getJSONObject(i).getString("summary");
dataObj.source = array.getJSONObject(i).getString("source");
dataObj.date = array.getJSONObject(i).getString("publish_date");
dataObj.termId = currentSearchTermDO.id;
//Reformat date
SimpleDateFormat format1 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
try {
Date date = format1.parse(dataObj.date);
SimpleDateFormat format2 = new SimpleDateFormat(SearchResultDO.DATE_FORMAT_STRING);
dataObj.date = format2.format(date);
} catch(ParseException pe) {
Log.e(TAG, pe.getMessage());
}
results.add(dataObj);
}
} catch(JSONException e){
Log.e(TAG, e.toString());
}
command.serviceComplete(results);
}
}
}
Well, since content length is reported in bytes, there is really no other way. If you want to use a StringReader you could take the length of each line you read and calculate the total bytes read to achieve the same thing. Also, the regular idiom is to check the return value of read() to check if you have reached the end of the stream. If, for some reason, the content length is wrong, your code may read more/less data then available. Finally, when converting a byte blob to a string, you should explicitly specify the encoding. When dealing with HTTP, you can get that from the 'charset' parameter of the 'Content-Type' header.
I had similar problem. I tried the solution of Jeremy C, but it was inaccurate, because value of "Content-Length" from header can be very different than real data.
My solution is:
Send HTTP header from server (PHP):
$string = json_encode($data, JSON_PRETTY_PRINT | JSON_FORCE_OBJECT);
header("X-Size: ".strlen($string)); //for example with name: "X-Size"
print($string);
Read correct value "X-size" for contentLength variable from HTTP header before read from stream:
protected String doInBackground(URL... urls) {
if (General.DEBUG) Log.i(TAG, "WebAsyncTask(doInBackground)");
String result = "";
BufferedReader reader = null;
try {
HttpURLConnection conn = (HttpURLConnection) urls[0].openConnection();
conn.setConnectTimeout(General.TIMEOUT_CONNECTION);
conn.setReadTimeout(General.TIMEOUT_SOCKET);
conn.setRequestMethod("GET");
conn.connect();
if (General.DEBUG) Log.i(TAG, "X-Size: "+conn.getHeaderField("X-Size"));
if (General.DEBUG) Log.i(TAG, "getHeaderField: "+conn.getHeaderFields());
if(conn.getResponseCode() != General.HTTP_STATUS_200)
return General.ERR_HTTP;
int contentLength = -1;
try {
contentLength = Integer.parseInt(conn.getHeaderField("X-Size"));
} catch (Exception e){
e.printStackTrace();
}
InputStream stream = conn.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder builder = new StringBuilder();
//Pokud delku zname:
if(contentLength > -1){
byte[] data = new byte[16]; //TODO
int totalRead = 0;
int bytesRead = 0;
while ((bytesRead = stream.read(data)) > 0){
Thread.sleep(100); //DEBUG TODO
try {
builder.append(new String(data, 0, bytesRead, "UTF-8"));
} catch (UnsupportedEncodingException e) {
Log.i(TAG, "Invalid charset: " + e.getMessage());
//Append without charset (uses system's default charset)
builder.append(new String(data, 0, bytesRead));
}
totalRead += bytesRead;
int progress = (int) (totalRead * (100/(double) contentLength));
Log.i(TAG, "length = " + contentLength + " bytesRead = " + bytesRead + " totalRead = " + totalRead + " progress = " + progress);
publishProgress(progress);
}
} else {
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line + '\n');
publishProgress(100);
}
}
result = builder.toString();
} catch (SocketException | SocketTimeoutException e){
if (General.DEBUG) Log.i(TAG, "SocketException or SocketTimeoutException");
e.printStackTrace();
return General.HTTP_TIMEOUT;
} catch (Exception e){
e.printStackTrace();
return General.ERR_HTTP;
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}