I'm looking on a way to run this task repeatedly with the listener. Right now, this is working but I'm looking on a way to make it repeatedly every 10 seconds.
Activity
public class SecondActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
VolleyRequest.makeRequest(this, URL, listenerResponse, listenerError);
}
private static final String URL = "https://naqil.ma/random.php";
private Response.Listener<JSONObject> listenerResponse = new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Toast.makeText(SecondActivity.this, "Resonse " + response.toString(), Toast.LENGTH_LONG).show();
}
};
private Response.ErrorListener listenerError = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(SecondActivity.this, "Error " + error, Toast.LENGTH_LONG).show();
}
};
}
Class making request
public class VolleyRequest {
public static void makeRequest(Context context, String url,
Response.Listener<JSONObject> listenerResponse, Response.ErrorListener listenerError) {
JsonObjectRequest requestWeather = new JsonObjectRequest(Request.Method.GET, url, null, listenerResponse,
listenerError);
Volley.newRequestQueue(context).add(requestWeather);
}
}
````
(Adapted from this answer: https://stackoverflow.com/a/10156550/2711811 )
Basically use a handler to reschedule request every 10 seconds. Handler is attached to main looper by virtue of creating it in onStart.
First, remove the VolleyRequest.makeRequest from onCreate.
Add members to SecondActivity:
private Handler myHandler;
private Runnable myRunnable;
In onStart of SecondActivity :
protected void onStart() {
super.onStart();
// Start issuing VolleyRequests repeating every 10 seconds.
myHandler = new Handler();
myHandler.post(new Runnable() {
#Override
public void run() {
SecondActivity.this.myRunnable = this;
VolleyRequest.makeRequest(
SecondActivity.this,
URL,
SecondActivity.this.listenerResponse,
SecondActivity.this.listenerError);
SecondActivity.this.myHandler.postDelayed(this, 10000);
}
};
}
And stop the repeated requests when the activity is stopped: in onStop of SecondActivity:
protected void onStop() {
super.onStop();
// check that it actually ran at least once - can't be null.
if (myRunnable != null) {
myHandler.removeCallbacks(myRunnable);
}
}
Related
I am new to android studio, I am making an app that gets the json of a field in thingspeak, but I don't know how can I make an auto refresh to the data I get every second. Can you please help me?
public class MainActivity extends AppCompatActivity {
private TextView mTextViewResult;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextViewResult = findViewById(R.id.text_view_result);
OkHttpClient client = new OkHttpClient();
// Read field url from thingspeak
String url = "https://api.thingspeak.com/channels/XXXXXXX/fields/1.json?api_key=XXXXXXXXXXXXX&results=2";
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onResponse(#NonNull okhttp3.Call call, #NonNull Response response) throws IOException {
if (response.isSuccessful()) {
// this is what I want to refresh every second
final String myResponse = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
mTextViewResult.setText(myResponse);
}
});
}
}
});
}
}
I found a solution finally, I placed the data request inside the following code and it worked perfectly:
final Handler handler = new Handler();
Runnable refresh = new Runnable() {
#Override
public void run() {
// data request
handler.postDelayed(this, 5000);
}
};
handler.postDelayed(refresh, 5000);
Use a CountDown Timer . Set the timer for 1 second and in onFinish method call request data .
new CountDownTimer(1000, 1000) {
public void onTick(long millisUntilFinished) {
}
public void onFinish() {
//Request Data
}
}.start();
I'm writing application and I want to call AsyncTask from BroadCastReceiver initialized in Service.
I want to AsyncTask do some work in background delayed, but it seems like a Handler not working, because I'm getting in Logcat this output(in short):
05-18 20:33:01.396 19382-19382// D/AsyncTask: Sleeping for a while
Sleeping for a while
.
.
05-18 20:33:01.406 19382-19382// D/AsyncTask: Sleeping for a while
Sleeping for a while
.
.
Here is my code:
ExampleService.java:
import java.util.*;
import android.content.*;
import com.google.firebase.messaging.*;
import timber.log.*;
public class ExampleService extends FirebaseMessagingService {
private AnotherExample anotherExample;
#Override
public void onMessageReceived(final RemoteMessage message) {
Timber.d("onMessageReceived(): message: %s", message);
anotherExample = new AnotherExample();
if (message.getData() != null) {
processMessage(message.getData());
}
}
private void processMessage(Map<String, String> data) {
Timber.d("processMessage(): data: %s", data);
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Timber.d("onReceiveScreenOff()");
anotherExample.create();
anotherExample.resume();
}
}, filter);
IntentFilter filter1 = new IntentFilter();
filter1.addAction(Intent.ACTION_SCREEN_ON);
registerReceiver(new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
Timber.d("onReceiveScreenOn()");
anotherExample.suspend();
}
}, filter1);
}
}
AnotherExample.java
public class AnotherExample {
AsyncTask asyncTask;
public void create() {
this.asyncTask = new MyAsyncTask();
}
public void resume() {
this.asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
public void suspend() {
this.asyncTask.cancel(true);
}
}
MyAsyncTask.java
public class MyAsyncTask extends AsyncTask {
private Handler handler;
private Runnable runnable;
private void setupRunnable() {
runnable = new Runnable() {
#Override
public void run() {
Log.d("AsyncTask", "Sleeping for a while");
}
};
}
#Override
protected Object doInBackground(Object[] objects) {
while (!isCancelled()) {
handler.postDelayed(runnable, 1000);
}
return null;
}
#Override
protected void onCancelled() {
super.onCancelled();
Log.d("AsyncTask", "Removing callbacks");
handler.removeCallbacks(runnable);
}
}
I don't know where the problem is, I also tried it with Thread.sleep(1000), but the result was same.
Is there any other way how to implement it?
Also I want to ask, is AsyncTask and BroadCastReceiver using same thread? Because it looks like BroadCastReceiver not getting information when screen is on.
Thanks for every advice.
I cannot reproduce your issue. My code seems to work fine.
Just call this:
private void testAsyncTaskDelay(){
TestEventsData test = new TestEventsData();
test.execute();
}
My TestEventsData class definition:
class TestEventsData extends AsyncTask<String, Integer, Boolean> {
Handler testHandler = new Handler();
#Override
protected Boolean doInBackground(String... params) {
Boolean success = false;
try {
long startTime = SystemClock.elapsedRealtime();
Log.e(TAG, "doInBackground Start " + startTime);
testHandler.postDelayed(new Runnable() {
#Override
public void run() {
long endTime = SystemClock.elapsedRealtime();
long diff = endTime - startTime;
Log.e(TAG, "run Start " + endTime);
Log.e(TAG, "run Start diff " + diff);
}
}, 3000);
}
catch (Exception ex) {
Log.e(TAG, "doInBackground --- " + ex.getMessage());
}
return success;
}
#Override
protected void onCancelled() {
}
#Override
protected void onPostExecute(Boolean success) {
try{
Log.e(TAG, "onPostExecute NOW");
}
catch(Exception ex){
Log.e(TAG, "onPostExecute" + ex.getMessage());
}
}
#Override
protected void onPreExecute() {
super.onPreExecute();
}
}
My output to logcat:
05-18 15:15:51.951 24329-24345/? E/MainActivity: doInBackground Start 1471880721
05-18 15:15:52.003 24329-24329/? E/MainActivity: onPostExecute NOW
05-18 15:15:54.953 24329-24329/com.asb.android.mcc E/MainActivity: run Start 1471883724
05-18 15:15:54.953 24329-24329/com.asb.android.mcc E/MainActivity: run Start diff 3003
Time difference 3003ms! Same time set in my postDelayed().
I am running a recursive handler which runs some code. I am posting the handler using a HandlerThread. I want to run the next recursive call only after the completion of the previous call.
Is it possible to do so? If not what are the alternatives.
HandlerThread ht = new HandlerThread();
ht.start();
Handler h = new Handler(ht.getLooper());
h.post(new Runnable() {
#override
public void run(){
//Some code
h.postDelay(this,1000);
}
});
Your code should work, but if you want a complete example how to run something recursively using HandlerThread, here it is:
public class Main2Activity extends AppCompatActivity {
private MyWorkerThread mWorkerThread;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mWorkerThread = new MyWorkerThread("myWorkerThread");
final Runnable task = new Runnable() {
#Override
public void run() {
Log.d("TAG", "Done.");
mWorkerThread.postTask(this);
}
};
mWorkerThread.start();
mWorkerThread.prepareHandler();
mWorkerThread.postTask(task);
}
#Override
protected void onDestroy() {
mWorkerThread.quit();
super.onDestroy();
}
}
class MyWorkerThread extends HandlerThread {
private Handler mWorkerHandler;
public MyWorkerThread(String name) {
super(name);
}
public void postTask(Runnable task){
mWorkerHandler.postDelayed(task, 1000); // set timeout which needed
}
public void prepareHandler(){
mWorkerHandler = new Handler(getLooper());
}
}
Don't forget to call handlerThread.quit() in onDestroy
Please guide me in this. Appreciate all your help.
My background service is toasting ABC
//-------------------String displayingText = "ABC";-----------------
And I have two strings, ABC and DEF declared in mainactivity.java
How do I pass the value displayingText from main activity to this service.
How do I change the displayingText to DEF after the toast ABC finished.
MyService.Java
public class MyService extends Service {
public static final long INTERVAL=3000;//variable to execute services every 5 second
private Handler mHandler=new Handler(); // run on another Thread to avoid crash
private Timer mTimer=null; // timer handling
//the get intent dont work. where or how should i put it?
Intent myIntent = getIntent();
if (myIntent !=null && myIntent.getExtras()!=null)
String value = myIntent.getExtras().getString(PassToService);
#Nullable
#Override
public IBinder onBind(Intent intent) {
throw new UnsupportedOperationException("unsupported Operation");
}
#Override
public void onCreate() {
// cancel if service is already existed
if(mTimer!=null)
mTimer.cancel();
else
mTimer=new Timer(); // recreate new timer
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(),0,INTERVAL);// schedule task
}
#Override
public void onTaskRemoved(Intent rootIntent) {
stopSelf();///its will stop service
super.onTaskRemoved(rootIntent);
}
#Override
public void onDestroy() {
Toast.makeText(this, "In Destroy", Toast.LENGTH_SHORT).show();//display toast when method called
mTimer.cancel();//cancel the timer
super.onDestroy();
}
//inner class of TimeDisplayTimerTask
private class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// display toast at every 10 second
//String displayingText = "ABC";
String displayingText = myIntent.getStringExtra("PassToService");
final Toast Notify = Toast.makeText(getApplicationContext(), displayingText, Toast.LENGTH_SHORT);
Notify.setGravity(Gravity.CENTER, 0, 0);
Notify.show();
Handler cancelToast = new Handler();
cancelToast.postDelayed(new Runnable() {
#Override
public void run() {
Notify.cancel();
}
}, 1000);
}
});
}
}
}
You can do it by passing value from activity to service-
startService(new Intent(YourActivity.Service.class).putExtra("key","value"));
I get this error "Can't create handler inside thread that has not called Looper.prepare()"
Can you tell me how to fix it?
public class PaymentActivity extends BaseActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.payment);
final Button buttonBank = (Button) findViewById(R.id.buttonBank);
buttonBank.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
progressDialog = ProgressDialog.show(PaymentActivity.this, "",
"Redirecting to payment gateway...", true, true);
new Thread() {
public void run() {
try {
startPayment("Bank");
} catch (Exception e) {
alertDialog.setMessage(e.getMessage());
handler.sendEmptyMessage(1);
progressDialog.cancel();
}
}
}.start();
}
});
StartPayment Method:
private void startPayment(String id) {
Bundle b = getIntent().getExtras();
final Sail sail = b.getParcelable(Constant.SAIL);
final Intent bankIntent = new Intent(this, BankActivity.class);
try {
Reservation reservation = RestService.createReservation(
sail.getId(),
getSharedPreferences(Constant.PREF_NAME_CONTACT, 0));
bankIntent.putExtra(Constant.RESERVATION, reservation);
// <workingWithDB> Storing Reservation info in Database
DBAdapter db = new DBAdapter(this);
db.open();
#SuppressWarnings("unused")
long rowid;
rowid = db.insertRow(sail.getId(), sail.getFrom(),
sail.getTo(), sail.getShip(), sail.getDateFrom().getTime(),
sail.getPrice().toString(), reservation.getId().floatValue());
db.close();
// </workingWithDB>
String html = PaymentService.getRedirectHTML(id, reservation);
bankIntent.putExtra(Constant.BANK, html);
} catch (Exception e) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
AlertDialog alertDialog = builder.create();
alertDialog.setMessage(e.getMessage());
alertDialog.show();
}
startActivity(bankIntent);
}
You should know that when you try to modify your UI , the only thread who can do that is the UiThread.
So if you want to modify your UI in another thread, try to use the method: Activity.runOnUiThread(new Runnable);
Your code should be like this :
new Thread() {
public void run() {
YourActivity.this.runOnUiThread(new Runnable(){
#Override
public void run(){
try {
startPayment("Bank");//Edit,integrate this on the runOnUiThread
} catch (Exception e) {
alertDialog.setMessage(e.getMessage());
handler.sendEmptyMessage(1);
progressDialog.cancel();
}
});
}
}
}.start();
I assume you create a Handler in startPayment() method. You can't do that, as handlers can be created on th UI thread only. Just create it in your activity class.
Instead of new Thread() line, try giving
this.runOnUiThread(new Runnable() {
you cant change any UI in thread you can use runOnUIThread or AsyncTask for more detail about this click here
I've found that most thread handling can be replaced by AsyncTasks like this:
public class TestStuff extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button buttonBank = (Button) findViewById(R.id.button);
buttonBank.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
new StartPaymentAsyncTask(TestStuff.this).execute((Void []) null);
}
});
}
private class StartPaymentAsyncTask extends AsyncTask<Void, Void, String> {
private ProgressDialog dialog;
private final Context context;
public StartPaymentAsyncTask(Context context) {
this.context = context;
}
#Override
protected void onPreExecute() {
dialog = new ProgressDialog(context);
// setup your dialog here
dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
dialog.setMessage(context.getString(R.string.doing_db_work));
dialog.setCancelable(false);
dialog.show();
}
#Override
protected String doInBackground(Void... ignored) {
String returnMessage = null;
try {
startPayment("Bank");
} catch (Exception e) {
returnMessage = e.getMessage();
}
return returnMessage;
}
#Override
protected void onPostExecute(String message) {
dialog.dismiss();
if (message != null) {
// process the error (show alert etc)
Log.e("StartPaymentAsyncTask", String.format("I received an error: %s", message));
} else {
Log.i("StartPaymentAsyncTask", "No problems");
}
}
}
public void startPayment(String string) throws Exception {
SystemClock.sleep(2000); // pause for 2 seconds for dialog
Log.i("PaymentStuff", "I am pretending to do some work");
throw new Exception("Oh dear, database error");
}
}
I pass in the Application Context to the Async so it can create dialogs from it.
The advantage of doing it this way is you know exactly which methods are run in your UI and which are in a separate background thread. Your main UI thread isn't delayed, and the separation into small async tasks is quite nice.
The code assumes your startPayment() method does nothing with the UI, and if it does, move it into the onPostExecute of the AsyncTask so it's done in the UI thread.
Try
final Handler handlerTimer = new Handler(Looper.getMainLooper());
handlerTimer.postDelayed(new Runnable() {
public void run() {
......
}
}, time_interval});