I changed my Manifest to target API 16 because of a thing with ActionBarSherlock, and since then my handler that checks the currently playing song is no longer working. It throws a NetworkOnMainThreadException on the line I marked below.
What am I doing wrong? I thought I had multithreading set up right.
Here's my code:
handler = new Handler();
updateSongTask = new Runnable() {
public void run() {
Log.d("asdf", "scraper started");
Scraper scraper = new ShoutCastScraper(); // THIS LINE throws the exception
List<Stream> streams;
try {
streams = scraper.scrape(new URI(url));
for (Stream stream : streams) {
Intent songIntent = new Intent(CUSTOM_INTENT);
String[] songAndArtist = songAndArtist(stream.getCurrentSong());
songIntent.putExtra("song", songAndArtist[0]);
songIntent.putExtra("artist", songAndArtist[1]);
songIntent.putExtra("stationurl", url);
sendBroadcast(songIntent);
Log.d("asdf", "should send broadcast" );
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
handler.postDelayed(this, 5000);
}
};
handler.postDelayed(updateSongTask, 0);
postDelayed() tells Android to run the Runnable on the main application thread after a delay. It does not run the Runnable on a background thread.
CommonsWare was right. I simply put an ASyncTask inside my handler and moved all my song update (worker) code into the doInBackground() method. Works great on all versions, and no network exception!
Related
i'm trying to achieve the following: do a single synchronous http request using Volley's Futures in a background thread, and have the current thread wait for the background thread to finish, so it can later handle the http response.
What actually happens is that after the .join(), everything seems to hang and I never enter the breakpoints inside the runnable's run method or get through to any command after the join().
NOTE - the current thread is an activity class, and this specific function is of a Java class whose services are called by the activity. I am aware that .join() on a UI thread causes it to hang...but only until the background thread is finished, right? Well, when I use .wait() instead of .join(), the background thread finishes really fast. It's almost as if calling join doesn't let the background thread do it's job.
private String requestConversionRatesFromApi() throws InterruptedException
{
final JSONObject[] localResponse = {null};
Runnable runnable = new Runnable()
{
#Override
public void run()
{
String url = "myurl";
RequestQueue queue = Volley.newRequestQueue(_context);
RequestFuture<JSONObject> future = RequestFuture.newFuture();
JsonObjectRequest request = new JsonObjectRequest(url, new JSONObject(), future, future);
queue.add(request);
try {
JSONObject jsonObject = future.get();
localResponse[0] = jsonObject; //doesn't get here either unless I'm using .wait() and then it happens really fast
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
};
Thread t = new Thread(runnable);
t.start();
t.join();
return "foo"; //Doesn't get here
}
I use the code below for getting some work done everytime after some time interval, and using post delay in 'finally' clause and oustide of runnable. Here is the code.
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
// do somthing
} catch (Exception e) {
// TODO: handle exception
} finally {
handler.postDelayed(this, 60000);
}
}
};
handler.postDelayed(runnable, 60000);
handler.postDelayed(runnable, 60000); will run two times or a single time.
it depends!
first matter
how the each try / catch / finally block completes normally or abruptly?
the finally block "always ^" executes when the try block exits
This ensures that the finally block is executed even if an unexpected exception occurs.
^ exception from above - finally may not be executed if jvm exits or thread gets killed
for details see java specs:
https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.2
second matter
how Handler post/postDelayed method executes will pass? or fails? for some reason - for second this may happen if message was not placed in to the message queue - on failure, usually because the looper processing the message queue is exiting.
but most likely your statement will make a INFINITE loop
** ps. you need to throw an exception in try block or remove catch block (as try{} finally{} ) can exist "without" catch but code in catch block without rising any exception will make a compiler complain (code will not compile)
if you want loop n-times+1 you need to add some condition before postDelayed in Runnable run() method
in your case code flow execution:
postDelayed method from last line outside definition of runnable
execution of runnable by:
start of try block
with or without passing catch
through finally block with postDelayed in runnable run() method - wich will place runnable in message que for delayed execution on main thread
then infinite loop on 2
so should i remove last postDelay out side of run() method to achieve postDelay run only ones in one loop. – AndroidMob
you can write this in such way:
final Handler handler = new Handler();
handler.post(new Runnable() {
// this int will also be passed to method post delayed
// as "this" keyword applies to Anonymous Class
// which body contains everything between brackets of new Runnable() { ... }
int withThis = 1;
#Override
public void run() {
handler.postDelayed(this,1000);
}
});
so where should i call method to get done somthing ? in run() method..? – AndroidMob
this also depends what you want to achieve:
example
handler.post(new Runnable() {
int counter = 0;
#Override
public void run() {
boolean wasPlacedInQue = false;
doPreMethod();
if(counter =< 10) {
doMethod();
wasPlacedInQue = handler.postDelayed(this,1000);
}
if(wasPlacedInQue) {
counter++;
doPostyMethod();
} else doFailureMethod();
}
the code in run() method is executed synchronously on so called UI Thread - i'ts main thread which executes your application see:
https://developer.android.com/training/multiple-threads/communicate-ui.html
if you are interested to study it more I have made a full working example for you:
https://gist.github.com/c3ph3us/7d237d540e60597369856cb1fa652a23
it surely will run two times. Because they are two different messages and handler will handle them separately.
My USB Host is receiving sensor data and it is getting updated every 200ms. I would like to read this data in my android app every 200ms. I am able to read it using bufferreader, It reads the data for sometime and then hangs. It is not consistent. I am new to this and may be I am not doing it the correct way. Below please find my code and let me know your suggestions. Thanks in advance.
public void startProcessOne()
{
new CountDownTimer(110,100)
{
#Override
public void onTick(long millisUntilFinished)
{
StringBuilder text = new StringBuilder();
line = "";
try {
FileReader in = new FileReader("/mnt/udisk/TEST.TXT");
BufferedReader br = new BufferedReader(in);
int i=0;
char[] buf = new char[10000];
while((i = br.read(buf,i,100))!= -1)
{
String h = new String(buf);
text.append(h);
text.append('\n');
}
br.close();
}
catch (IOException e) {
//You'll need to add proper error handling here
}
TxtRead.setText(text.toString());
}
#Override
public void onFinish()
{
startProcessOne();
}
}.start();
}
TxtRead.setText(text.toString());
This line is causing the problem. You can't touch UI elements from a background thread. You should instead run those codes in the UI/Main thread.
In your case, I'd personally prefer using Java threads. So, create a background thread to keep running periodically. If you would need to run UI methods from that background thread. You probably need a handler attached to the main thread.
// Instantiate a handler in UI thread
final Handler handler = new Handler();
new Thread(new Runnable(){
// Once you're done and want to break the loop, just set this boolean
private boolean stopped = false;
#Override
public void run(){
while(!stopped) {
// Read from the file
// Whenever you need to update an UI element,
// you should wrap it inside this runnable object
handler.post(new Runnable(){
#Override
public void run(){
// Update UI
TxtRead.setText("new_text");
}
})
try {
// This thread will sleep for 9 seconds
Thread.Sleep(9000);
} catch(Exception e){}
}
}
}).start();
I am getting this error, and my application crashes:
java.lang.IllegalStateException: The current thread must have a looper!
I didn't get much about how to use looper on Google, I am using threads(mainly for sleep function), handler(for downloading the image while Async task is running) and Async task(for getting the JSON data from the URL). I have no idea how to resolve this issue, so any suggestions will be vey helpful.
This is the code for the thread which is executed on click of the button:
View view = flingContainer.getSelectedView();
view.findViewById(R.id.item_swipe_right_indicator).setAlpha((float) 1.0);
Thread timer = new Thread() {
public void run() {
try {
sleep(320);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
flingContainer.getTopCardListener().selectLeft();
}
}
};
timer.start();
I am using this libray and log-cat is:
where: at com.enormous.quotesgram.MainActivity$3.run(MainActivity.java:479) in last in log-cat corresponds to the line: flingContainer.getTopCardListener().selectLeft(); in above piece of code.
Try the following (unfortunately I cannot test the code):
Thread timer = new Thread() {
public void run() {
try {
sleep(320);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
runOnUiThread(new Runnable() {
#Override
public void run() {
flingContainer.getTopCardListener().selectLeft();
}
});
}
}
};
The idea behind is, that the Timer thread is not a Looper thread (resulting in an exception saying "The current thread must have a looper"). The UI thread however, is a Looper thread (see for instance this site).
As flingContainer.getTopCardListener().selectLeft() is probably designed to run on the UI thread it fails, if it not invoked in side of a pipelined thread.
in the below code send() function is executing many times in a second,i want to execute send() once in a second,how i change the code
timer.scheduleAtFixedRate(
new TimerTask() {
public void run() {
try {
send();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
},
1000,
1000);
send function is given below
void send() throws Exception, IOException
{
s=new Socket("10.0.2.2",4200);
r=new PrintWriter(s.getOutputStream());
while(true)
{
Log.e("msg","hi send\n");
r.print("hai");
}
}
Logcat output is given below
I replaced timers with Runnables/Handlers recently, it's much easier
//declare at top of your activity
private Handler h = new Handler();
private Runnable myRunnable = new Runnable() {
public void run() {
//do stuff
//run again in one second
h.postDelayed(myRunnable, 1000);
}
};
//trigger the runnable somewhere in your code e.g. onClickHander or onCreate etc
h.postDelayed(myRunnable, 1000);
It happened for me when I used a TaskTimer and the phone got into sleep mode. I think it is related to TimerTask using Thread.sleep() to provide the timing. This relies on uptimeMillis() which according to documentation - 'is counted in milliseconds since the system was booted. This clock stops when the system enters deep sleep (CPU off, display dark, device waiting for external input), but is not affected by clock scaling, idle, or other power saving mechanisms. This is the basis for most interval timing such as Thread.sleep(millls)'
Solution would be either to use AlarmManager or WakeLocks.
an easier approach would look like this:
new Thread() {
public void run() {
while(true) {
send();
try{
Thread.sleep(1000); // pauses for 1 second
catch(Exception e) {}
}
}
}.start();