There is my code and action after sink.close(); should change text of the textview but it isn't happening. Why?
protected void runNet() throws IOException {
try{
final OkHttpClient client = new OkHttpClient();
final Request request = new Request.Builder()
.url("http://uprojects.pl/radiowezel/questions.db")
.build();
Response response = client.newCall(request).execute();
QuestionsDB db = new QuestionsDB(context);
File downloadedFile = new File(context.getDatabasePath("questions.db"), "");
BufferedSink sink = Okio.buffer(Okio.sink(downloadedFile));
sink.writeAll(response.body().source());
sink.close();
status.setText("Baza została zaktualizowana");
}catch(UnknownHostException e){
status.setText ("Brak połączenia przy pobieraniu");
}
}
You are trying to update UI from background thread which is not allowed in Android, you should update it from main thread.
You can use runOnUiThread method (part of Activity class)
private void updateUi(final String string) {
runOnUiThread(new Runnable() {
#Override
public void run() {
status.setText(string);
}
});
}
you can use followed method, call it from background thread like this:
updateUi("Baza została zaktualizowana");
Or use AsyncTask which has callback which runs after execution on main thread - AsyncTask Android example
Also you can use Handler - Running code in main thread from another thread
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
}
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 want to use Espresso to test web calls. I've made a small test app to see if I can get this to work without using AsyncTask. Upon getting data back, a TextView tells the user whether the call was successful or not. I'm making the web call in a new thread.
In my test, I tried following the AdvancedSynchronizationTest as a pattern to making the test wait until the web request is fulfilled. My implementation, however, doesn't seem to work. My understanding is that the method that I'm overriding is ending before the callback is returned to the main activity. If that's the case, I'm overwriting the wrong class. I've also tried overriding runnable itself (see example below) and even changed the UI update to simply setting a boolean, but with no different outcome. Obviously, Espresso doesn't like my using another thread, but why doesn't it pick up that it should wait until the thread is complete? What would be an alternative without using AsyncTask?
You can see the whole project here: https://github.com/bqmackay/EspressoCustomThreadingResourceExample.
Here is the code in question:
MainActivityTest
public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
...
#Override
protected void setUp() throws Exception {
super.setUp();
getActivity();
Runnable runnable = getActivity().getDownloadHelper().getWebCallRunnable();
CountingIdlingResource countingIdlingResource = new CountingIdlingResource("WebCallRunnableCall");
getActivity().getDownloadHelper().setWebCallRunnable(new DecoratedWebCallRunnable(runnable, countingIdlingResource));
registerIdlingResources(countingIdlingResource);
}
public void testThreadRetrieval() throws Exception {
onView(withText("Thread")).perform(click());
assertTrue(getActivity().isDidThreadReturn());
//onView(withText("Thread Retrieved")).check(matches(isDisplayed()));
}
private class DecoratedWebCallRunnable implements Runnable {
private final Runnable realRunnable;
private final CountingIdlingResource countingIdlingResource;
private DecoratedWebCallRunnable(Runnable realRunnable, CountingIdlingResource countingIdlingResource) {
this.realRunnable = realRunnable;
this.countingIdlingResource = countingIdlingResource;
}
#Override
public void run() {
countingIdlingResource.increment();
try {
realRunnable.run();
} finally {
countingIdlingResource.decrement();
}
}
}
DownloadHelper
public class DownloadHelper {
private Runnable webCallRunnable;
private Runnable createWebCallRunnable() {
return new Runnable() {
#Override
public void run() {
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = null;
try {
response = httpclient.execute(new HttpGet("http://whoismyrepresentative.com/getall_mems.php?zip=84020"));
StatusLine statusLine = response.getStatusLine();
if(statusLine.getStatusCode() == HttpStatus.SC_OK){
ByteArrayOutputStream out = new ByteArrayOutputStream();
response.getEntity().writeTo(out);
out.close();
repsCallbackInterface.onRepsThreadReceived(true);
} else{
//Closes the connection.
response.getEntity().getContent().close();
repsCallbackInterface.onRepsThreadReceived(false);
throw new IOException(statusLine.getReasonPhrase());
}
} catch (IOException e) {
e.printStackTrace();
}
}
};
}
}
MainActivity
public class MainActivity extends Activity implements RepsCallbackInterface {
....
#Override
public void onRepsThreadReceived(final boolean didReceive) {
setDidThreadReturn(true);
runOnUiThread(new Runnable() {
#Override
public void run() {
threadText.setText(didReceive ? "Thread Retrieved" : "Thread Failed");
}
});
}
}
You didn't really provide a question here, so I assume the question is about why this setup is not working as expected.
There are (at least) two reasons:
The assert assertTrue(getActivity().isDidThreadReturn());in testThreadRetrieval() does not wait at all for IdlingResources to be finished. Only ViewInteraction.check() and ViewInteraction.perform() are aware of those and will check IdlingResources before trying to apply the ViewAssertion or ViewAction.
Even if the commented out line after the assertTrue() is applied instead, it would not work, because the instrumentation thread is independent and doesn't wait for the new thread created in getReps() to start, so the check of IdlingResources can and will happen before the CountingIdlingResource is incremented.
If, for whatever reason, you really don't want to use an AsyncTask, you still can profit from Espresso watching the AsynTask thread pool by using its executor. So instead of starting a separate thread, just submit the Runnable to the AsyncTask.THREAD_POOL_EXECUTOR.
I've been working on an android app which regularly checks a mysql database using JSON and everything works fine with my code.
Im having trouble running this as a timer as it only runs once and then stops.
The only code i managed to get working runs the http request on the UI thread which freezes up.
Any help would be most appreciated.
Thank in advance,
#Override
protected void onCreate(Bundle savedInstanceState) {
...
checkUpdate.start();
...
}
private Thread checkUpdate = new Thread() {
public void run() {
try {
// my code here to get web request to return json string
}
String response = httpclient.execute(httppost, responseHandler);
mHandler.post(showUpdate);
}
...
}
private Runnable showUpdate = new Runnable(){
public void run(){
try{
// my code here handles json string as i need it
Toast.makeText(MainActivity.this,"New Job Received...", Toast.LENGTH_LONG).show();
showja();
}
}
}
private void showja(){
Intent i = new Intent(this, JobAward.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i);
finish();
}
As #Raghunandan suggested, the standard way to perform work in the background on Android, and then modify the UI when that work is done, is using AsyncTask.
First define a new subclass of AsyncTask:
private class JsonRequestTask extends AsyncTask<HttpUriRequest, Void, String> {
protected String doInBackground(HttpUriRequest... requests) {
// this code assumes you only make one request at a time, but
// you can easily extend the code to make multiple requests per
// doInBackground() invocation:
HttpUriRequest request = requests[0];
// my code here to get web request to return json string
String response = httpclient.execute(request, responseHandler);
return response;
}
protected void onPostExecute(String jsonResponse) {
// my code here handles json string as i need it
Toast.makeText(MainActivity.this, "New Job Received...", Toast.LENGTH_LONG).show();
showja();
}
}
and then you would use the task like this, instead of your Thread:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
JsonRequestTask task = new JsonRequestTask();
task.execute(httppost);
...
}
You may run the task again by simply creating a new JsonRequestTask() and calling its execute() method.
A common practice for a simple async task like this is to make it a private inner class within the Activity class that uses it (if only one Activity needs it). You may need to change the scope of some of your activity's variables so that the inner class may use them (e.g. move local variables to member variables).
I have an app with an httprequest. I wanted to set a timeout for that request, and since I can't control de DNS timeout a user from stackoverflow suggested to create a Thread with a timer to cancel the request after a certain time, and that's what I'm doing.
In my new Thread I use Thread.sleep to wait 30 seconds and, when that time finishes, cancel the request if it hasn't ended, but my Thread never wakes up. This is my code:
private Thread timeout_request = new Thread(new Runnable() {
public void run() {
try{
Log.d(TAG, "Thread start");
Thread.sleep(30000);
Log.d(TAG, "Thread awake");
if(!httprequest_finished){
request_aborted = true;
mHttpClient.getConnectionManager().shutdown();
}
}catch(Exception e){
e.printStackTrace();
}
}
});
public String sendData(String token){
...
timeout_request.start();
Log.i(TAG, "Sending request");
final HttpResponse resp = httpClient.execute(post);
Log.i(TAG, "Execute finished");
if(request_aborted) return null;
httprequest_finished = true;
...
}
If I execute the sendData function without internet connection the log shows "Sending request" and "Thread start", but doesn't show "Thread awake" or "Execute finished" (I've waited like 5 minutes). Why is that?
------ EDIT ------
By the way, I don't know if it matters, but I'm using ThreadSafeClientConnManager in my connection.
I've tested a few thing:
1- Replace HttpResponse resp = httpClient.execute(post) with while(!request_aborted). The thread awakes (it works).
2- Use mHandler.postDelayed(r, 30000) instead of a Thread. I'm still executing httpClient.execute(post). Result: the Runnable is NOT launched.
private Handler mHandler = new Handler();
private Runnable r = new Runnable() {
public void run() {
Log.d(TAG, "Runnable()");
if(!httprequest_finished){
request_aborted = true;
mHttpClient.getConnectionManager().shutdown();
}
}
};
3- Use mHandler.postDelayed(r, 30000) instead of a Thread. Replace HttpResponse resp = httpClient.execute(post) with while(!request_aborted). Result: the Runnable is NOT launched.
So the thread works if I'm not executing the http request, but the handler never works. I noticed these lines in my log:
threadid=3: reacting to signal 3
Wrote stack traces to '/data/anr/traces.txt'
threadid=3: reacting to signal 3
Wrote stack traces to '/data/anr/traces.txt'
This appears 6 or 7 seconds after executing the thread or setting the handler. I've tried to use:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread paramThread, Throwable paramThrowable) {
Log.e("Alert","Lets See if it Works !!!");
}
});
But the log never shows "Lets See if it Works !!!". I looked the traces.txt file and I don't understand what it's saying -.-
I have tested the following code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package javaapplication1;
/**
*
* #author paro
*/
public class JavaApplication1 {
public boolean req_aborted = false;
public Thread timeout_request = new Thread(new Runnable() {
public void run() {
try{
System.out.println("start");
Thread.sleep(30000);
System.out.println("awake");
if(req_aborted ==false)
{
req_aborted = true;
System.out.println("flag change");
}
}catch(Exception e){
e.printStackTrace();
}
}
});
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
JavaApplication1 jap = new JavaApplication1();
jap.timeout_request.start();
System.out.println("requset started");
if(jap.req_aborted)
{
System.out.println("flag is true now");
}
}
}
and the output is
requset started
start
awake
flag change
seems that no problem with the thread related part of your code.
and your code's logic says it should print "awake". seems that you are having problem with the following statement
final HttpResponse resp = httpClient.execute(post);
Rather than using Thread.sleep I think you should be using Handler.postDelayed. Have a look at the documentation.
Something like:
Handler mHandler = new Handler();
...
mhandler.postDelayed(new Runnable() {
public void run() {
if(!httprequest_finished){
request_aborted = true;
mHttpClient.getConnectionManager().shutdown();
}
}
}, 30000);
This will execute the passed in Runnable after the specified delay.