I write a simple AsyncTask which:
#Override
protected Void doInBackground(Void... params) {
for (int i = 0; i <= 99; i++) {
long time = System.currentTimeMillis();
try {
//Wait for 6ms
Thread.sleep(6);
} catch (InterruptedException e) {
e.printStackTrace();
}
long diff = System.currentTimeMillis() - time;
Log.d(TAG, "Row "i + " is DONE with timeDiff=" + diff + "ms vs. waitTime=" + waitTime + "ms");
publishProgress(i);
}
}
It works well in some of test devices until I try on LG devices (Nexus 4, G3): time to sleep seems longer than I think. After checking log, I see in normal case, timeDiff is 6ms or 7ms; while with LG devices, timeDiff is mostly > 40ms.
Also try to use SystemClock.sleep() but no luck.
Could anyone please suggest me how to fix it? Any help would be appreciated!
Alternate solution is use Handler for wait.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
//call after delay
}
}, 2000);
Related
I writing an android timer app that uses System.nanotime. The issue is that it's giving me underpredicted results as well negative numbers. redVal, blueVal, and greenVal are updated on each frame of the camera.
results
504455566
-95947265
9063721
61035
-99487305
-98937988
12664795
-75317382
code
for (testAmount = 0; testAmount < 80; testAmount++) {
runOnUiThread(new Runnable() {
public void run() {
lagSquare.setBackgroundColor(Color.rgb(255, 255, 255));
lagStartTime = System.nanoTime(); //start lagTimer start
}
});
while (redVal <= 100.0 && blueVal <= 100.0 && greenVal <= 100.0) {
x=0;
}
runOnUiThread(new Runnable() {
public void run() {
lagEndTime = System.nanoTime(); //start lagTimer end
lagSquare.setBackgroundColor(Color.rgb(000, 000, 000));//set lagSquare black
}
});
lagTimeResult = (lagEndTime - lagStartTime);
timeArray[testAmount] = lagTimeResult;
Log.i("LTR", String.valueOf(lagTimeResult));
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
You are trying to output a time difference which is relying upon values being set in different threads, without any synchronization. This will almost always end up with the wrong value:
for (testAmount = 0; testAmount < 80; testAmount++) {
// this will schedule the Runnable to run *sometime* in
// the future - but not necessarily right now
runOnUiThread(new Runnable() {
public void run() {
lagStartTime = System.nanoTime(); //start lagTimer start
}
});
// this will also schedule this Runnable to run *sometime* in
// the future - but not necessarily after the first one
runOnUiThread(new Runnable() {
public void run() {
lagEndTime = System.nanoTime(); //start lagTimer end
}
});
// this will probably execute first (before either of
// the other Runnables have completed)
lagTimeResult = (lagEndTime - lagStartTime);
}
You simply can't rely on the order of threads executing in the order you've coded them - and definitely not in a loop.
I can't understand from your question what you are trying to time, but the take-home rule is that whenever you have multiple threads, you can never rely on the order of execution without using some form of synchronization.
I am using JSch to perform an SFTP download in Android. This is on a LAN with 802.11n and an SFTP server on a wired gigabit connection. I am getting about 8 mbytes/sec on a laptop (also 802.11n) with the same code but I am only getting 40kbytes/sec on Android. Are there some flags or something I need to turn on to get this to transfer faster? I have tried it on a Nexus 5 and a Nexus 6, both with 5.1. I tried a couple of apps and one downloaded the file at 230kbytes/sec and the other right around 40kbytes/sec so I'm guessing one of them has the same issue I do.
Here is my code:
public class MainActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Thread thread = new Thread() {
#Override
public void run() {
try {
JSch jsch = new JSch();
jsch.setConfig("StrictHostKeyChecking", "no");
Session session = jsch.getSession("ftptest", "192.168.1.205");
session.setPort(22);
session.setPassword("password");
session.connect();
ChannelSftp channel = (ChannelSftp) session.openChannel("sftp");
channel.connect();
SftpProgressMonitor monitor = new SftpProgressMonitor() {
long finalCount = 0;
long start = -1;
#Override
public void init(int op, String src, String dest, long max) {
start = System.currentTimeMillis();
}
#Override
public boolean count(long count) {
finalCount += count;
/* long took = (System.currentTimeMillis() - start) / 1000;
if (took > 0) {
Log.w("SFTP", "Transferred so far " + finalCount + " at speed bytes/sec " + (finalCount / took));
}*/
return true;
}
#Override
public void end() {
long took = (System.currentTimeMillis() - start) / 1000;
Log.w("SFTP", "Transferred " + finalCount + " in " + took + " speed bytes/sec " + (finalCount / took ));
}
};
InputStream stream = channel.get("file", monitor);
int read = -1;
byte[] bs = new byte[8192];
while((read = stream.read(bs)) >= 0){
//do nothing
}
} catch (JSchException e) {
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
thread.start();
}
}
EDIT: It seems to be much faster (about 160kbytes/sec) if I tell it to write the stream into a file without giving me an InputStream. The code looks pretty different between the two get methods but even if I went that route, 160kbytes/sec is still much slower than I had hoped.
What version of Android are you testing with? Can you adb shell in and see what these settings are (when you're on wifi)?
cat /proc/sys/net/ipv4/tcp_rmem
cat /proc/sys/net/ipv4/tcp_wmem
And then if they are low (something like "4092 8760 11680"), then try setting them to larger values:
sudo echo "524288,1048576,2097152" > /proc/sys/net/ipv4/tcp_rmem
sudo echo "262144,524288,1048576" > /proc/sys/net/ipv4/tcp_wmem
Then try your test again.
This could be from a bug where the wifi buffers were being set too small in some cases (https://code.google.com/p/android/issues/detail?id=64706).
Have you tried wrapping your stream in a buffering stream?
BufferedInputStream bis = new BufferedInputStream(channel.get("file", monitor));
8192 bytes seems like a small buffer...
Also make sure you close your connections/streams, maybe you have a lot of outgoing connections you don't know about that's hogging the hardware?
How can I improve the performance of the code below? I have created method that will execute some other Method if Minute and Second of hour is 0, but I am still using looping and that is lagging my phone up to 30% mem usage, is there any suggestion to do that ?
this is my code
try {
do {
if ((Calendar.getInstance().get(Calendar.MINUTE) == 0) && (Calendar.getInstance().get(Calendar.SECOND) == 0)){
UtilitiesService.InitLoggingService(getApplicationContext());
blnPerfect = true;
//return null;
break;
//stopSelf();
}
} while (!blnPerfect);
} catch (Exception e) {
e.printStackTrace();
}
You can calculate the time to 0,0 and Start a Single Shot thread
Executors.newSingleThreadScheduledExecutor().schedule(new Callable() {
public Void call() {
doSomething();
return null;
}
}, X, TimeUnit.SECONDS);
Why don't you simply calculate how long you have to wait until the time is at the ZEROth minute and ZEROth second ... but seeing how long you need to wait, converting to milliseconds, an sleeping for that long?
Also, you should do this "event" timing in an asynchronous task/thread.
when started, my android application loads some image from a remote server using an Asynchronous task. Sometimes, when the connection is too weak, it takes a long time to load and it's not great.
how can i add timeout to this task, so that if the activity can't load the images after 10 seconds for example, the user will get an error message
use AsyncTask and then show the progress bar for 10 seconds. if it exceeds more than that 10 sec show the log message .
AsyncTask
You can try something like this
private static final int MAX_ATTEMPTS = 5;
static class Task extends AsyncTask<String, Integer, Integer> {
protected Integer doInBackground(String... vals) {
try {
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
Log.d(TAG, "Attempt #" + i + " to server connection");
try {
//DO STUFF
} catch (IOException e) {
if (i == MAX_ATTEMPTS) {
break;
}
try {
Log.d(TAG, "Sleeping for " + backoff + " ms before retry");
Thread.sleep(backoff);
} catch (InterruptedException e1) {
Log.d(TAG, "Thread interrupted: abort remaining retries!");
Thread.currentThread().interrupt();
return 400;
}
// increase backoff exponentially
backoff *= 2;
}
}
} catch (Exception e) {
Log.e(TAG, "ERROR", e);
}
return 400;
}
protected void onPostExecute(Integer success) {
}
}
But I suggest you look at Volley, Google's new networking library. That will serve you best. I use this code above in one of my upload methods
if you are using .net web services for get data from server then use below:
HttpTransportSE aht1 = new HttpTransportSE(URL, 60000);
Where, URL is your connection url of webservices. here, it waits for 1 minute for get response. after that it throws error of timeout.
I made an app that downloads videos from our server.
The issue is:
When i cancel the downloading i call:
myAsyncTask.cancel(true)
I noticed, that myAsyncTask doesn't stops on calling cancel... my ProgressDialog still goes up and its like jumping from status to status showing me that each time I cancel and start again an AsyncTask by clicking the download button, a new AsyncTask starts...
Each time I click download.. then cancel, then again download a separate AsyncTask starts.
Why is myAsynTask.cancle(true) not cancelling my task ? I don't want it anymore on the background. I just want to completely shut it down if I click cancel.
How to do it ?
E D I T:
Thanks to gtumca-MAC, and the others who helped me did it by:
while (((count = input.read(data)) != -1) && (this.isCancelled()==false))
{
total += count;
publishProgress((int) (total * 100 / lenghtOfFile));
output.write(data, 0, count);
}
Thanks!!!
AsyncTask does not cancel process on
myAsynTask.cancel(true)
For that you have to stop it manually.
for example you are downloading video in doInBackground(..) in while/for loop.
protected Long doInBackground(URL... urls) {
for (int i = 0; i < count; i++) {
// you need to break your loop on particular condition here
if(isCancelled())
break;
}
return totalSize;
}
Declare in your class
DownloadFileAsync downloadFile = new DownloadFileAsync();
then On Create
DownloadFileAsync downloadFile = new DownloadFileAsync();
downloadFile.execute(url);
in Your Background ()
if (isCancelled())
break;
#Override
protected void onCancelled(){
}
and you can kill your AsyncTask by
downloadFile.cancel(true);
When you start a separate thread(AyncTask) it has to finish. You have to manually add a cancel statement to your code inside the AsyncTask.
A task can be cancelled at any time by invoking cancel(boolean). Invoking this method will cause subsequent calls to isCancelled() to return true. After invoking this method, onCancelled(Object), instead of onPostExecute(Object) will be invoked after doInBackground(Object[]) returns. To ensure that a task is cancelled as quickly as possible, you should always check the return value of isCancelled() periodically from doInBackground(Object[]), if possible (inside a loop for instance.)
Checkout more in the documentation: http://developer.android.com/reference/android/os/AsyncTask.html
I have been researching from the last 2 weeks and I don't get to know that how we kill the Async operation manually. Some developers use BREAK; while checking in for loop. But on my scenario I am not using the loop inside of background thread.
But I have got to know how it woks its a stupid logic but works perfectly fine.
downloadFile.cancel(true); //This code wont work in any case.
Instead of canceling and doing so much work on background thread turn off the wifi programmatically
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(false);
where do you want to kill the operation and turn on it where do you need that.
WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
wifi.setWifiEnabled(true);
What happens is your try block jumps in to the IOException killing the background tasks.
You better use vogella asyncTask library which have a lot of features like priority and canceling background task. And a great tutorial or using it is here
You can use this code. I am downloading a OTA file as follow:
static class FirmwareDownload extends AsyncTask<String, String, String> {
public String TAG = "Super LOG";
public String file;
int lenghtOfFile;
long total;
#Override
protected String doInBackground(String... f_url) {
try {
int count;
Utilies.getInternet();
URL url = new URL(f_url[0]);
URLConnection connection = url.openConnection();
connection.connect();
lenghtOfFile = connection.getContentLength();
mProgressBar.setMax(lenghtOfFile);
InputStream input = new BufferedInputStream(url.openStream(), 8192);
String fileName = f_url[0].substring(f_url[0].lastIndexOf("/"), f_url[0].length());
File root = Environment.getExternalStorageDirectory();
File dir = new File(root.getAbsolutePath() + fileName);
Log.d(TAG, "trying to download in : " + dir);
dir.getAbsolutePath();
OutputStream output = new FileOutputStream(dir);
byte data[] = new byte[1024];
while ((count = input.read(data)) != -1) {
if (isCancelled())
break;
total += count;
mProgressBar.setProgress(Integer.parseInt("" + total));
Log.d("Downloading " + fileName + " : ", " " + (int) ((total * 100) / lenghtOfFile));
mPercentage.post(new Runnable() {
#Override
public void run() {
mPercentage.setText(total / (1024 * 1024) + " Mb / " + lenghtOfFile / (1024 * 1024) + " Mb");
}
});
output.write(data, 0, count);
}
output.flush();
output.close();
input.close();
//new InstallHelper().commandLine("mkdir data/data/ota");
File fDest = new File("/data/data/ota/" + fileName);
copyFile(dir, fDest);
FirmwareInstaller fw = new FirmwareInstaller();
fw.updateFirmware();
} catch (Exception a) {
System.out.println("Error trying donwloading firmware " + a);
new InstallHelper().commandLine("rm -r data/data/ota");
dialog.dismiss();
}
return null;
}
}
So, If you want to cancel, just use this code:
fDownload.cancel(true);
I have used with success inside an activity with TextView onclick ...
//inside the doInBackground() ...
try {
while (true) {
System.out.println(new Date());
//should be 1 * 1000 for second
Thread.sleep(5 * 1000);
if (isCancelled()) {
return null;
}
}
} catch (InterruptedException e) {
}
and in my onCreate() ...
//set Activity
final SplashActivity sPlashScreen = this;
//init my Async Task
final RetrieveFeedTask syncDo = new RetrieveFeedTask();
syncDo.execute();
//init skip link
skip_text = (TextView) findViewById(R.id.skip_text);
skip_text.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//cancel Async
syncDo.cancel(true);
//goto/start another activity
Intent intent = new Intent();
intent.setClass(sPlashScreen, MainActivity.class);
startActivity(intent);
finish();
}
});
and my xml TextView element ...
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/skip_text"
android:layout_marginTop="20dp"
android:text="SKIP"
android:textColor="#color/colorAccent"/>